Win32 API взаимоблокировки при использовании разных потоков

Я испытываю тупик при попытке использовать WIN32 API из дополнительного потока. Дополнительный поток необходим в моем приложении, чтобы улучшить частоту кадров. Это действительно помогает, однако, я получаю взаимоблокировки почти во всех системных функциях:

::Витрина
:: MoveWindow
:: UpdateWindow

Я знаю, что ShowWindow (), например, может быть заменен на ShowWindowAsync (), и это действительно решает проблему, однако в MoveWindow () и UpdateWindow () таких альтернатив нет.

Кто-то испытывал эти проблемы, что является решением?

Спасибо!

1

Решение

Термин «взаимоблокировка» описывает очень специфическую вещь: два потока ожидают доступа к ресурсу, заблокированному другим. Нет никаких признаков того, что это то, что происходит в вашем случае (или есть?), Так что именно вы испытываете? Кроме того, что именно вы хотите достичь с помощью многопоточности?

В любом случае, сохраняйте пользовательский интерфейс в одном потоке, используйте SendMessage () & Co, чтобы уведомить этот поток о любых событиях, происходящих в фоновых потоках. Кроме того, вы также можете использовать таймер для опроса определенных изменений состояния. Таким образом, вы на безопасной стороне, и ваше приложение не должно блокироваться (по крайней мере, из-за использования интерфейса из разных потоков).

Чтобы быть более точным, вы должны держать цикл сообщений для окна и всех его дочерних окон в одном потоке. Вы можете создать несколько окон и обрабатывать каждое из них из своего собственного потока, но не смешивайте вызовы. На практике это различие не важно, хотя, потому что немногие приложения создают несколько окон (и нет, например, окно сообщения или другие диалоги не учитываются).

1

Другие решения

Все функции API, на которые вы ссылаетесь, имеют общее свойство: они отправляют (!) Какое-то сообщение целевому окну. UpdateWindow, вероятно, является наиболее очевидным, потому что он должен отправить WM_PAINT. Также обратите внимание, что он «отправляет» сообщение и не публикует его в очереди (для UpdateWindow документация MSDN вызывает это явно, для других это может быть менее очевидно).

Также обратите внимание, что окна имеют родство нитей как упоминалось в некоторых комментариях. Среди прочего это означает, что сообщения в это окно только когда-либо принимаются / отправляются в одном потоке. Если вы отправляете сообщение в окно другого потока, операционной системе остается задача определить, когда она должна отправить это сообщение (т.е. вызвать оконную процедуру). Это (отправка входящих отправленных сообщений) происходит только во время определенных вызовов API, во время которых можно предположить, что безопасно вызывать оконную процедуру со случайным сообщением. Соответствующее время — во время GetMessage и PeekMessage *.

Таким образом, если ваш поток-владелец окна (также называемый потоком пользовательского интерфейса) нормально перекачивает сообщения, входящие отправленные сообщения также быстро отправляются. Из вашего вопроса, однако, кажется, что ваш поток пользовательского интерфейса в настоящее время занят. Если второй поток затем вызывает одну из указанных функций, он будет блокироваться до тех пор, пока первый поток не предоставит возможность отправки отправленных сообщений.

Как уже говорили другие, обычно хорошей идеей является сохранение кода пользовательского интерфейса в одном выделенном потоке пользовательского интерфейса (хотя исключения — как всегда — подтверждают правило). И, безусловно, необходимо (для хорошего пользовательского опыта), чтобы потоки, владеющие окнами, всегда реагировали на сообщения. Если ваш поток пользовательского интерфейса также должен ждать некоторых объектов синхронизации, вам может пригодиться MsgWaitForMultipleObjects.

* список может быть неполным.

1

По вопросам рекламы [email protected]