В каких случаях необходимо использовать потоки?
От: vpchelko  
Дата: 31.01.07 13:30
Оценка:
На проекте столкнулся с проблемой (написано очень много кода, и приходится его разгребать). Не стабильно появляются зависания UI.
Дело в том, что для каждого запроса используется модель:
запрос делается в потоке (поток может зависнуть), а приложение ждет когда поток отработает запрос по типу WaitForSignal(timeInterval), на время ожидания приложение зависает в некоторых местах стоит даже InfiniteTimeout .

Единственное, что приходит в голову переписать всё на#ер. Но заказчик на это не пойдёт.

Подскажите, пожалуйста, какую-нибудь схему, чтобы убрать подобные зависания с минимальными изменениями кода. Ибо от изучения такого кода, начинают мозги разжижаться, и уже ни чего не соображаешь ...
Сало Украине, Героям Сала
Re: В каких случаях необходимо использовать потоки?
От: Celestial Россия http://video.google.com/googleplayer.swf?docId=1055185227485133586
Дата: 31.01.07 13:38
Оценка: +1
Здравствуйте, vpchelko, Вы писали:

V>На проекте столкнулся с проблемой (написано очень много кода, и приходится его разгребать). Не стабильно появляются зависания UI.

V>Дело в том, что для каждого запроса используется модель:
V>запрос делается в потоке (поток может зависнуть), а приложение ждет когда поток отработает запрос по типу WaitForSignal(timeInterval), на время ожидания приложение зависает в некоторых местах стоит даже InfiniteTimeout .

V>Единственное, что приходит в голову переписать всё на#ер. Но заказчик на это не пойдёт.


V>Подскажите, пожалуйста, какую-нибудь схему, чтобы убрать подобные зависания с минимальными изменениями кода. Ибо от изучения такого кода, начинают мозги разжижаться, и уже ни чего не соображаешь ...


Тебе нужно централизовать обработку запросов, т.е. написать транспортный уровень через который и будет происходить общение клиента с сервером, и тогда будет достаточно в классе "транспорт" сделать правильный поток ...
Re[2]: В каких случаях необходимо использовать потоки?
От: Lloyd Россия  
Дата: 31.01.07 13:40
Оценка: 1 (1) -1
Здравствуйте, Celestial, Вы писали:

C>Тебе нужно централизовать обработку запросов, т.е. написать транспортный уровень через который и будет происходить общение клиента с сервером, и тогда будет достаточно в классе "транспорт" сделать правильный поток ...


Столько умных слов, а ничего не понятно. Ты лучше на пальцах покажи, чем наличие/отсутствие транспортного слоя поможет ему с проблемой зависания UI?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: В каких случаях необходимо использовать потоки?
От: AlexVinS Россия  
Дата: 31.01.07 14:16
Оценка: +4
Здравствуйте, vpchelko, Вы писали:

V>На проекте столкнулся с проблемой (написано очень много кода, и приходится его разгребать). Не стабильно появляются зависания UI.

V>Дело в том, что для каждого запроса используется модель:
V>запрос делается в потоке (поток может зависнуть), а приложение ждет когда поток отработает запрос по типу WaitForSignal(timeInterval), на время ожидания приложение зависает в некоторых местах стоит даже InfiniteTimeout .

V>Единственное, что приходит в голову переписать всё на#ер. Но заказчик на это не пойдёт.


V>Подскажите, пожалуйста, какую-нибудь схему, чтобы убрать подобные зависания с минимальными изменениями кода. Ибо от изучения такого кода, начинают мозги разжижаться, и уже ни чего не соображаешь ...


Когда запускается запрос в новом потоке, ждать его не надо. Можно задизаблить интерфейс той формы в которую придут данные (а с другими можно работать). Если используется какой-нить Grid можно его зделать недоступным а поверх его вывести надпись "Дождитесь выполнения запроса"
Когда поток отработает, он отправляет сообщение в форму (или Event взводит или еще что-то).
После этого данные выводятся в Форму.
И все довольны)


Умный человек знает не многое, но нужное
Re[3]: В каких случаях необходимо использовать потоки?
От: Аноним  
Дата: 08.02.07 19:11
Оценка: +1
Здравствуйте, Lloyd, Вы писали:

L>Столько умных слов, а ничего не понятно. Ты лучше на пальцах покажи, чем наличие/отсутствие транспортного слоя поможет ему с проблемой зависания UI?


Если на пальцах: WaitFor-функции НЕ должны вызываться из визуального (основного) потока, иначе GUI "замерзнет" до конца интервала или прихода сообщения. Для этого должен быть специальный поток. А он уже кидает в основной поток PostMessage() при завершении WaitFor-функции.
Re[4]: В каких случаях необходимо использовать потоки?
От: Lloyd Россия  
Дата: 10.02.07 18:40
Оценка:
Здравствуйте, Аноним, Вы писали:

L>>Столько умных слов, а ничего не понятно. Ты лучше на пальцах покажи, чем наличие/отсутствие транспортного слоя поможет ему с проблемой зависания UI?


А>Если на пальцах: WaitFor-функции НЕ должны вызываться из визуального (основного) потока, иначе GUI "замерзнет" до конца интервала или прихода сообщения. Для этого должен быть специальный поток. А он уже кидает в основной поток PostMessage() при завершении WaitFor-функции.


Уже лучше. Но все-таки хотелось бы понять как связаны транспортный слой и отсутствие/наличие WaitFor-ов?
Re[5]: В каких случаях необходимо использовать потоки?
От: kliff Россия http://www.esignal.ru
Дата: 11.02.07 11:37
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Здравствуйте, Аноним, Вы писали:


L>>>Столько умных слов, а ничего не понятно. Ты лучше на пальцах покажи, чем наличие/отсутствие транспортного слоя поможет ему с проблемой зависания UI?


А>>Если на пальцах: WaitFor-функции НЕ должны вызываться из визуального (основного) потока, иначе GUI "замерзнет" до конца интервала или прихода сообщения. Для этого должен быть специальный поток. А он уже кидает в основной поток PostMessage() при завершении WaitFor-функции.


L>Уже лучше. Но все-таки хотелось бы понять как связаны транспортный слой и отсутствие/наличие WaitFor-ов?


Варианта два.

1. Оставить ожидание в потоке UI. Тогда нужно переписать функцию WaitFor таким обрахом чтобы она показывала юзеру что происходит — прогресс или обычный диалог с надписью waiting. Самый простой способ.

2. Вынести ожидание запросов в отдельный поток. Но только если UI не должен ждать завершения запроса. Т.е. если UI рассчитан на работу во время пока запрос еще не завершен.
Re[6]: В каких случаях необходимо использовать потоки?
От: Lloyd Россия  
Дата: 11.02.07 16:27
Оценка:
Здравствуйте, kliff, Вы писали:

L>>>>Столько умных слов, а ничего не понятно. Ты лучше на пальцах покажи, чем наличие/отсутствие транспортного слоя поможет ему с проблемой зависания UI?


А>>>Если на пальцах: WaitFor-функции НЕ должны вызываться из визуального (основного) потока, иначе GUI "замерзнет" до конца интервала или прихода сообщения. Для этого должен быть специальный поток. А он уже кидает в основной поток PostMessage() при завершении WaitFor-функции.


L>>Уже лучше. Но все-таки хотелось бы понять как связаны транспортный слой и отсутствие/наличие WaitFor-ов?


K>Варианта два.


K>1. Оставить ожидание в потоке UI. Тогда нужно переписать функцию WaitFor таким обрахом чтобы она показывала юзеру что происходит — прогресс или обычный диалог с надписью waiting. Самый простой способ.


K>2. Вынести ожидание запросов в отдельный поток. Но только если UI не должен ждать завершения запроса. Т.е. если UI рассчитан на работу во время пока запрос еще не завершен.


Молодец, очень интересно. Но все-таки хотелось бы понять причем здесь "транспортный слой"?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: В каких случаях необходимо использовать потоки?
От: Nuald Россия http://nuald.blogspot.com
Дата: 12.02.07 10:09
Оценка:
Здравствуйте, vpchelko, Вы писали:

V>запрос делается в потоке (поток может зависнуть), а приложение ждет когда поток отработает запрос по типу WaitForSignal(timeInterval), на время ожидания приложение зависает в некоторых местах стоит даже InfiniteTimeout .


Ну надо просто ждать не только сообщений от потоков, но и виндовозные сообщения, и их обрабатывать. Мы примерно делали так (проект на VC 6):
void CSimpleThread::WaitForComplete() {
    while (!alreadyDie) {
        HANDLE hCompleteEvent = completeEvent;
        DWORD dwResult = MsgWaitForMultipleObjectsEx(1, &hCompleteEvent,
                INFINITE, QS_PAINT | QS_SENDMESSAGE | QS_MOUSEBUTTON | 
                QS_KEY | QS_HOTKEY
                , 0);
        switch (dwResult) {
            case WAIT_OBJECT_0:
                alreadyDie = true;
                break;
            case WAIT_OBJECT_0 + 1:
                HandleMessagesInQueue();
                break;
        }
    }
}

inline void CSimpleThread::HandleMessagesInQueue() {
    GUIUtils::ProcessMessages(ASMDProgressDialogWin::GetProgressDlgHandle());
}

void GUIUtils::ProcessMessages(HWND hWnd) {
    MSG msg; 
    while (PeekMessage(&msg, 0,  0, 0, PM_REMOVE)) {
        if (msg.message == WM_QUIT) {
            ::PostQuitMessage(0);
            break;
        }
        if (!hWnd || !IsDialogMessage(hWnd, &msg)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
}

Т.е. используется MsgWaitForMultipleObjectsEx. Если приходит сообщение от потока (hCompleteEvent), то ожидание закончено (ставится соответствующий флаг — в данном случае, alreadyDie). Если же нет, то происходит обработка сообщений (CSimpleThread::HandleMessagesInQueue, который вызывает GUIUtils::ProcessMessages).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.