Посылка сообщений в worker thread...
От: Serop  
Дата: 05.12.01 16:36
Оценка:
Создаю "Worker Threads" через AfxBeginThread, посылаю в срэд сообщения и принимаю их в цикле функции threadProc()... Все, вроде, нормально принимается, но вот как дело доходит до завершения, почему-то сообщения пропадают, и хуже того, срэд "замерзает", т.е. цикл функции перестает выполняться, хотя WaitForSingleObject() и GetExitCodeThread() говорят, что срэд еще живой, активный (что происходит конткретно — долго объяснять) Причем, эффект наблюдается не каждый раз, а, например, 3 раза срэд нормально завершается, а на четрвертый раз — "виснет".
И подумал я, а какого собственно я создаю рабочйи срэд вместо User-Interface Thread? MSDN говорит, что у рабочего срэда нет message pump. Может из-за этого у меня проблемы? Какой тип срэда лучше использовать? (в срэде я не работаю с GUI объектами, поэтому сначала и не делал UI thread)

Спасибо заранее.
http://wiki.swrus.com — shareware FAQ
Re: Посылка сообщений в worker thread...
От: Admiral Украина  
Дата: 05.12.01 18:25
Оценка: 3 (1)
Здравствуйте Serop, Вы писали:

S>И подумал я, а какого собственно я создаю рабочйи срэд вместо User-Interface Thread? MSDN говорит, что у рабочего срэда нет message pump. Может из-за этого у меня проблемы? Какой тип срэда лучше использовать? (в срэде я не работаю с GUI объектами, поэтому сначала и не делал UI thread)


S>Спасибо заранее.


Насколько я помню, в Win32 нету потоков разных типов. Их различают по наличию очереди сообщений.
Если рабочему потоку отправить сообщение, то очередь сообщений создастся автоматом, и такой поток станет называться User-Interface Thread. А по дэфолту ее (очереди) нету.

Для оповещения потока я предпочитаю использовать event-ы (через CreateEvent(), SetEvent() и пр.).
В общем, если операции, выполняемые "работягой" , можно разбить на несколько этапов, то попробуй event-ы.

Удачи!
Re[2]: Посылка сообщений в worker thread...
От: Serop  
Дата: 05.12.01 19:17
Оценка:
Здравствуйте Admiral, Вы писали:

A>Насколько я помню, в Win32 нету потоков разных типов. Их различают по наличию очереди сообщений.

A>Если рабочему потоку отправить сообщение, то очередь сообщений создастся автоматом, и такой поток станет называться User-Interface Thread. А по дэфолту ее (очереди) нету.
Спасибо! Интересная инфо и полезная.

A>Для оповещения потока я предпочитаю использовать event-ы (через CreateEvent(), SetEvent() и пр.).

A>В общем, если операции, выполняемые "работягой" , можно разбить на несколько этапов, то попробуй event-ы.
Дело в том, что переделать под эвенты пока, боюсь не получится, ибо проект никто не даст ломать. Мне бы выяснить, куда эти мессаги вдруг деваются.... Что за засада
http://wiki.swrus.com — shareware FAQ
Re[3]: Посылка сообщений в worker thread...
От: VVV Россия  
Дата: 05.12.01 19:53
Оценка: 3 (1)
Здравствуйте Serop, Вы писали:

S>Здравствуйте Admiral, Вы писали:



S>Дело в том, что переделать под эвенты пока, боюсь не получится, ибо проект никто не даст ломать. Мне бы выяснить, куда эти мессаги вдруг деваются.... Что за засада


очень похоже на deadlock (причём это очень сложно ловится, к сожалению), например: главная нитка (с главным окном) решает завершиться, шлёт в другую нитку сообщение о завершении и садится в WaitForSingleObject(, INFINITE) ждать когда же та закончит свою работу, а в этот момент (может быть и сообщение о завершении ещё не пришло) та нитка решает послать в главное (или другое в главной нитке) окно сообщение с помощью SendMessage() и.... тут то deadlock и пришёл, т.к. главная нить сидит в WaitForXXX и не обрабатывает очередь сообщений, а SendMessage без ответа тоже не завершится.
Re[4]: Посылка сообщений в worker thread...
От: Serop  
Дата: 05.12.01 20:03
Оценка:
Здравствуйте VVV, Вы писали:

S>>Дело в том, что переделать под эвенты пока, боюсь не получится, ибо проект никто не даст ломать. Мне бы выяснить, куда эти мессаги вдруг деваются.... Что за засада


VVV>очень похоже на deadlock (причём это очень сложно ловится, к сожалению), например: главная нитка (с главным окном) решает завершиться, шлёт в другую нитку сообщение о завершении и садится в WaitForSingleObject(, INFINITE) ждать когда же та закончит свою работу, а в этот момент (может быть и сообщение о завершении ещё не пришло) та нитка решает послать в главное (или другое в главной нитке) окно сообщение с помощью SendMessage() и.... тут то deadlock и пришёл, т.к. главная нить сидит в WaitForXXX и не обрабатывает очередь сообщений, а SendMessage без ответа тоже не завершится.


Ух ты! Точно-точно, что-то очень близкое: мой трабловый срэд в цикле вызывает метод класса, который посылает в главное приложение сообщение. Только я использую PostThreadMessage для их отправки в главное приложение, т.е. не жду подтверждения о приеме....
И пока не понятно, где этот дэдлок случается, почему срэд виснет? Может ли функция PostThreadMessage не вернуться, если, например главное приложение, в которое посылается это сообщение уже находится в "состоянии нестояния" — ExitInstance()?
Ну, чудеса...
Спасибо за ответ, это натолкнуло на новые мысли!
http://wiki.swrus.com — shareware FAQ
Re[4]: Посылка сообщений в worker thread...
От: Serop  
Дата: 05.12.01 21:12
Оценка:
VVV>очень похоже на deadlock (причём это очень сложно ловится, к сожалению), например: главная нитка (с главным окном) решает завершиться, шлёт в другую нитку сообщение о завершении и садится в WaitForSingleObject(, INFINITE) ждать когда же та закончит свою работу, а в этот момент (может быть и сообщение о завершении ещё не пришло) та нитка решает послать в главное (или другое в главной нитке) окно сообщение с помощью SendMessage() и.... тут то deadlock и пришёл, т.к. главная нить сидит в WaitForXXX и не обрабатывает очередь сообщений, а SendMessage без ответа тоже не завершится.

И что интересно, когда главное приложение выходит (не дождавшись) из WaitForSingleObject, нитка моя, трабловая, отмерзает и нагло так завершается, как ни в чем не бывало, радостно записывая в лог, что она отработала... млин...
http://wiki.swrus.com — shareware FAQ
Re[5]: Посылка сообщений в worker thread...
От: IT Россия linq2db.com
Дата: 05.12.01 21:31
Оценка: 3 (1)
Здравствуйте Serop, Вы писали:

S>Ух ты! Точно-точно, что-то очень близкое: мой трабловый срэд в цикле вызывает метод класса, который посылает в главное приложение сообщение. Только я использую PostThreadMessage для их отправки в главное приложение, т.е. не жду подтверждения о приеме....


PostThreadMessage, да ещё и в цикле? Вообще-то с такими вещами нужно аккуратно, по крайней мере нужно быть уверенным, что сообщения шлются не часто. А можно запросто очередь у принимающего процесса забить. Хотя она большая и резиновая, но при определённой снаровке забивается на раз
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Посылка сообщений в worker thread...
От: Serop  
Дата: 05.12.01 21:37
Оценка:
Здравствуйте IT, Вы писали:

IT>PostThreadMessage, да ещё и в цикле? Вообще-то с такими вещами нужно аккуратно, по крайней мере нужно быть уверенным, что сообщения шлются не часто. А можно запросто очередь у принимающего процесса забить. Хотя она большая и резиновая, но при определённой снаровке забивается на раз

Да от тож... Уже рассматриваю этот вопрос, как "чистить" очередь мессаджей у главного приложения, хотя, чую, чревато это... Есть опыть в подобных извратах?
Задача даже стоит подругому: как почистить очередь, соответствующую нитке с известным хэндлером/ID? (жуть, вопросов становится не меньше, а больше...)

Спасибо
http://wiki.swrus.com — shareware FAQ
Re[5]: Посылка сообщений в worker thread...
От: Alex Fedotov США  
Дата: 05.12.01 21:42
Оценка: 3 (1)
Здравствуйте Serop, Вы писали:

VVV>>очень похоже на deadlock (причём это очень сложно ловится, к сожалению), например: главная нитка (с главным окном) решает завершиться, шлёт в другую нитку сообщение о завершении и садится в WaitForSingleObject(, INFINITE) ждать когда же та закончит свою работу, а в этот момент (может быть и сообщение о завершении ещё не пришло) та нитка решает послать в главное (или другое в главной нитке) окно сообщение с помощью SendMessage() и.... тут то deadlock и пришёл, т.к. главная нить сидит в WaitForXXX и не обрабатывает очередь сообщений, а SendMessage без ответа тоже не завершится.


S>И что интересно, когда главное приложение выходит (не дождавшись) из WaitForSingleObject, нитка моя, трабловая, отмерзает и нагло так завершается, как ни в чем не бывало, радостно записывая в лог, что она отработала... млин...


1. Ставишь в вызов WaitForSingleObject INFINITE.
2. Запускашь, все зависает, как и ожидалось.
3. Прерываешь программу отладчиком и смотришь, что делают потоки. Главный поток висит на WaitForSingleObject, а твой что в это время делает? Я думаю, как только ты увидишь, в каком вызове засыпает твой поток, объяснение происходящему будет простым и очевидным.

Не гадайте на кофейной гуще, пользуйтесь отладчиками — они rulez.
-- Alex Fedotov
Re[7]: Посылка сообщений в worker thread...
От: IT Россия linq2db.com
Дата: 05.12.01 22:11
Оценка: 3 (1)
Здравствуйте Serop, Вы писали:

S>Здравствуйте IT, Вы писали:


S>Да от тож... Уже рассматриваю этот вопрос, как "чистить" очередь мессаджей у главного приложения, хотя, чую, чревато это... Есть опыть в подобных извратах?


Никак его не надо чистить, надо использовать SendMessage. Производительность, якобы дающая эффект при использовании функций Post*, в большинстве случаев, мнимая, и ни к чему кроме как к проблемам не приводящая. И уж точно при интенсивном обмене данными между потоками этими функциями пользоваться не стоит.
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Посылка сообщений в worker thread...
От: Serop  
Дата: 05.12.01 22:12
Оценка:
Привет, Alex Fedotov!
Спасибо за ответ, большая честь для меня.. Вижу Вас в самых разных форумах...
Ну, так к делу:

AF>1. Ставишь в вызов WaitForSingleObject INFINITE.

AF>2. Запускашь, все зависает, как и ожидалось.
AF>3. Прерываешь программу отладчиком и смотришь, что делают потоки. Главный поток висит на WaitForSingleObject, а твой что в это время делает? Я думаю, как только ты увидишь, в каком вызове засыпает твой поток, объяснение происходящему будет простым и очевидным.

AF>Не гадайте на кофейной гуще, пользуйтесь отладчиками — они rulez.


1 — стоит
2 — зависает, но не всегда, раз в 4 запуска
3 — прерываю, а как увидеть, на каком месте срэд мой стоит? Смотреть между строк дисассемблерного кода, который генерячит дебагер при нажатии на паузу? Там мне нифига не понятно.. Не могу я попасть в свою нитку, которая чего-то вдруг ждать стала и, главное, в каком месте... Ну тупой я, тупой
4 — так ими же и пользуемся, может не всегда эффективно

Спасибо!

ЗЫ — ща трейсами облажу всё, пусть спам гонит, но узнаю, где собака, т.е. нитка, зарылась!
http://wiki.swrus.com — shareware FAQ
Re[8]: Посылка сообщений в worker thread...
От: Serop  
Дата: 05.12.01 22:25
Оценка:
IT>Никак его не надо чистить, надо использовать SendMessage. Производительность, якобы дающая эффект при использовании функций Post*, в большинстве случаев, мнимая, и ни к чему кроме как к проблемам не приводящая. И уж точно при интенсивном обмене данными между потоками этими функциями пользоваться не стоит.

Постараюсь учесть в будущем, а ща нужно этот фиксить (чужое творение)...

Мессаджи посылаются основной нитке не часто, там таймаут стоит, ну раз 5 в секунду.
Post-ы они бывают в некоторых случаях удобными и незаменимыми (для квази-распараллеливания процессов), но вот в моем случае вылезло боком, и пока не пойму каким и куда.
Не догоняю чего я...
Говорила мама, читай, сынок, книжки про Multithreading and Win32 Messages... Не послушался

Спасибо еще раз!
http://wiki.swrus.com — shareware FAQ
Re[7]: Посылка сообщений в worker thread...
От: Alex Fedotov США  
Дата: 06.12.01 01:26
Оценка: 7 (2)
Здравствуйте Serop, Вы писали:

AF>>1. Ставишь в вызов WaitForSingleObject INFINITE.

AF>>2. Запускашь, все зависает, как и ожидалось.
AF>>3. Прерываешь программу отладчиком и смотришь, что делают потоки. Главный поток висит на WaitForSingleObject, а твой что в это время делает? Я думаю, как только ты увидишь, в каком вызове засыпает твой поток, объяснение происходящему будет простым и очевидным.

AF>>Не гадайте на кофейной гуще, пользуйтесь отладчиками — они rulez.


S>1 — стоит

S>2 — зависает, но не всегда, раз в 4 запуска
S>3 — прерываю, а как увидеть, на каком месте срэд мой стоит? Смотреть между строк дисассемблерного кода, который генерячит дебагер при нажатии на паузу? Там мне нифига не понятно.. Не могу я попасть в свою нитку, которая чего-то вдруг ждать стала и, главное, в каком месте... Ну тупой я, тупой

1. Поставить NT Debug Symbols (optional, but helps much)
2. Включить опцию "Load COFF & Exports" в Tools|Options... -> Debug tab.
3. Использовать команду Debug|Threads для переключения между потоками и окно Call Stack, чтобы посмотреть, где поток находится в данный момент.

P.S. Статью при использование MSDN написали, теперь надо написать статью про использование отладчика.
-- Alex Fedotov
Re[8]: Посылка сообщений в worker thread...
От: IT Россия linq2db.com
Дата: 06.12.01 01:42
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>P.S. Статью при использование MSDN написали, теперь надо написать статью про использование отладчика.


Нужно обязательно. Отладка потоков, прикол Влада с ax,hr (он у меня теперь в watch по умолчанию болтается ), у Алексея Остапенко в статье про ISAPI есть намёк на малоизвестную вкладку Debug->Additional DLLs, JIT, стек... в общем, много чего. Может получится хорошая статья.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Посылка сообщений в worker thread...
От: Sashko Россия http://www.dc.baika.ru/
Дата: 06.12.01 02:13
Оценка: 2 (1)
Здравствуйте Admiral, Вы писали:

A>Насколько я помню, в Win32 нету потоков разных типов. Их различают по наличию очереди сообщений.

A>Если рабочему потоку отправить сообщение, то очередь сообщений создастся автоматом, и такой поток станет называться User-Interface Thread. А по дэфолту ее (очереди) нету.

Неточность, очередь сообщений создается в момент, когда нитка (созданная и еще не имеющая очереди сообщения) вызывает USER'овскую функцию (CreateWindow, GetMessage etc). А так можно хоть заотправляться в нее сообщениями, очередь создаваться не будет.
Re[8]: Посылка сообщений в worker thread...
От: Serop  
Дата: 06.12.01 03:03
Оценка:
AF>1. Поставить NT Debug Symbols (optional, but helps much)
AF>2. Включить опцию "Load COFF & Exports" в Tools|Options... -> Debug tab.
AF>3. Использовать команду Debug|Threads для переключения между потоками и окно Call Stack, чтобы посмотреть, где поток находится в данный момент.

AF>P.S. Статью при использование MSDN написали, теперь надо написать статью про использование отладчика.


Ну вот, теперь же совсем другое дело!
Спасибо огромное, а статья такая, думаю, не помешала бы, однозначно!
http://wiki.swrus.com — shareware FAQ
Re[3]: Спасибо всем огромное! ... но, вопросы остались :)
От: Serop  
Дата: 06.12.01 03:28
Оценка:
Здравствуйте Sashko, Вы писали:

S>Неточность, очередь сообщений создается в момент, когда нитка (созданная и еще не имеющая очереди сообщения) вызывает USER'овскую функцию (CreateWindow, GetMessage etc). А так можно хоть заотправляться в нее сообщениями, очередь создаваться не будет.


Очень интересно!!!
Объяснитесьб сударь!
Я пока не могу понять двух вещей:
1 — всегда ли можно посылать в нитку сообщения (PostThreadMessage), независимо от того, есть ли у нее очередь сообщений или нет???? Если очереди нет, а посылать можно, а главное, получать его в нитке тоже можно, то, вновь прешедшее сообщение будет "затирать" предыдущее, необработанное? (а где это одно сообщение хранится? а если хранится одно, почему нет места для других?.. странно это всё, точно нужно умные книжки почитать
2 — Если есть очередь сообщений, всегда ли должен быть "message pump" организованный системой или базовым классом? или он может быть "самодельным"? (думаю, скорее второе)
3 — опционально не монимаю: правильно ли использовать методику передачи сообщений таким образом между нитями, особенно когда могут возникать замкнутые контуры?... Кажется, что это стратегически неверно, а нужно использовать методу синхронизации потоков (нитей) через эвенты, семафоры и т.д.?

Я только учусь, поэтому многое не понятно...
Может кто порекомендует книжку умную про ЭТО, можно импортную — буду оч. признателен.

Еще раз спасибо за ответы всем, будет желание — поделитесь инфой еще


Удачи
http://wiki.swrus.com — shareware FAQ
Re[8]: И чего делать? :)
От: Serop  
Дата: 06.12.01 16:03
Оценка:
AF>1. Поставить NT Debug Symbols (optional, but helps much)
AF>2. Включить опцию "Load COFF & Exports" в Tools|Options... -> Debug tab.
AF>3. Использовать команду Debug|Threads для переключения между потоками и окно Call Stack, чтобы посмотреть, где поток находится в данный момент.

AF>P.S. Статью при использование MSDN написали, теперь надо написать статью про использование отладчика.


Вот чего я поимел в процессе отладки
DBG: Break command failed within 3 seconds.
DBG: Potential deadlock. Soft broken.
:)

Буду бороться дальше :)
http://wiki.swrus.com — shareware FAQ
Re[9]: И чего делать? :)
От: Alex Fedotov США  
Дата: 06.12.01 17:12
Оценка:
Здравствуйте Serop, Вы писали:

S>Вот чего я поимел в процессе отладки

S>DBG: Break command failed within 3 seconds.
S>DBG: Potential deadlock. Soft broken.

Ничего особенно страшного. Продолжить выполнение программы скорее всего не удастся, но проанализировать текущее состояние это не помешает.
-- Alex Fedotov
Re[10]: ЗАРАБОТАЛО! (кажись)
От: Serop  
Дата: 06.12.01 18:34
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>Здравствуйте Serop, Вы писали:


S>>Вот чего я поимел в процессе отладки

S>>DBG: Break command failed within 3 seconds.
S>>DBG: Potential deadlock. Soft broken.

AF>Ничего особенно страшного. Продолжить выполнение программы скорее всего не удастся, но проанализировать текущее состояние это не помешает.


Ну, короче, никто мне не сказал....
А сделал я так:

while (TRUE) {
    DWORD result;
    MSG msg;
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        DispatchMessage(&msg);
    result = MsgWaitForMultipleObjects(1, &pThread->m_hThread, FALSE, INFINITE, QS_ALLINPUT);
    if (result == (WAIT_OBJECT_0 + 1))
        continue;
    else
        break;
    }


Оказывается, НЕЛЬЗЯ просто сидеть в WaitForSingleObject, если нитка является главной в приложении!!!
Нуна еще и мессаджи пропускать, хоть иногда
Короче, теперь тестирую, кажется, дэдлок пропал
Окончательные результаты сообщу.

Спасибо.
http://wiki.swrus.com — shareware FAQ
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.