Тупик с отключенной нитью - PullRequest
1 голос
/ 22 декабря 2010

Я пишу многопоточное приложение на основе диалога с Visual C ++. Имеет несколько просмотров.

Функция OnInitialUpdate. Я запускаю рабочий поток следующим образом:

pThread = AfxBeginThread(MultiThread, this, THREAD_PRIOIRITY_NORMAL, 0 CREATE_SUSPENDED, NULL);
pThread->m_bAutoDelete = false;
pThread->ResumeThread();

функция OnDestroy у меня есть

eventKill.SetEvent();
WaitForSingleObject(pHread->m_hThread, INFINITE);
delete pThread

Функция MultiThread имеет

...
while (WaitForSingleObject(pView->eventKill.m_hObject, 0) != WAIT_OBJECT_0)
{
    ...
    pView->InvalidateRect(rect);
    pView->UpdateWindow();
    Sleep(100);
}
return 0;

Обычно это нормально завершается, но я нашел одно исключение. У меня есть эта тема и ее представление работает. Существует еще одно представление, которое в настоящее время находится сверху, а представление потока частично находится под ним. Если я закрываю представление потока, непосредственно нажимая его кнопку закрытия, но не заставляю этот поток просматривать самое верхнее окно, программа блокируется в WaitForSingleObject (pThread-> m_hThread, INFINITE). Если я не использую UpdateWindow, не будет тупиков. Если я сделаю просмотр потока самым верхним, прежде чем нажать кнопку закрытия, проблем тоже не будет. Так почему тупик?

Ответы [ 2 ]

1 голос
/ 22 декабря 2010

Функция UpdateWindow () может выполняться только до тех пор, пока поток, которому принадлежит окно, не отправит событие WM_PAINT. Этого не может быть, поток пользовательского интерфейса блокируется при вызове WaitForSingleObject. Этот вызов никогда не может быть завершен, поток заблокирован на UpdateWindow. Тупик.

Этот вид кода съест вас заживо, если вы не соблюдаете жесткие и жесткие правила потоков с пользовательским интерфейсом. Ни user32, ни gdi не являются поточно-ориентированными. Поток пользовательского интерфейса может никогда не блокировать без прокачки сообщений. Вы должны использовать MsgWaitForMultipleObjectsEx (). Рабочий поток не должен никогда напрямую использовать любые функции API, которые влияют на окно. Только системные сообщения автоматически маршалируются, вместо этого используйте PostMessage (), чтобы поток пользовательского интерфейса мог выполнять обновления.

0 голосов
/ 23 декабря 2010

Я не знал, что UpdateWindow продолжает ждать WM_PAINT.Я думаю также InvalidateRect не потокобезопасен, даже когда он не ждет WM_PAINT.Я изменил свой рабочий поток, чтобы использовать PostMessage.Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...