Подтвердить что ты не робот

Как это возможно: OnPaint обрабатывается в WaitOne

У меня есть ManualResetEvent. В какой-то момент я жду этого события, используя WaitOne. К моему удивлению, я получил событие OnPaint, а в WaitOne. Это случается довольно часто.

Трассировка стека выглядит следующим образом:

alt text

Я понял, что WaitOne блокирует текущий поток и не разрешит выполнение какого-либо другого кода до тех пор, пока не произойдет событие.

Может ли кто-нибудь объяснить, что здесь происходит?

4b9b3361

Ответ 1

Это по дизайну. CLR выполняет контракт на однопоточную квартиру (STA). Основной поток приложения GUI - это STA, как требуется в программировании Windows, атрибут [STAThread] в методе Main() гарантирует, что.

Жесткие правила для потока STA - это то, что он должен перекачать контур сообщения (например, Application.Run) и никогда не блокировать. Блокирование потока STA с большой вероятностью может привести к тупиковой ситуации, когда фоновые потоки используют любые объекты, связанные с COM-квартирой. Их много, буфер обмена и WebBrowser являются общими, с которыми вы столкнетесь в .NET-программе. Многие менее заметные, также доступные в качестве классов оболочки .NET.

CLR гарантирует, что блокировка не может вызвать блокировку путем перекачки цикла сообщения при использовании оператора блокировки или вызова метода Wait для классов синхронизации. Или Thread.Join(). Этот цикл сообщений отправляет сообщение WM_PAINT, в результате чего выполняется событие Paint.

Вам необходимо реструктурировать свою программу, чтобы это не вызвало проблемы. Очень важно сосредоточиться на том, чтобы не блокировать основной поток. Это очень редко необходимо, если у вас есть, скажем, класс BackgroundWorker или Control.BeginInvoke(). По какой-то нечетной причине класс Mutex не делает такого рода перекачку, это может быть другим способом. Хотя тупик скрывается за углом, если вы это делаете.

Ответ 2

Я тоже видел это поведение для оператора lock(). По-видимому, классы .net Framework Thread начинают цикл сообщений, ожидая блокировки в потоке пользовательского интерфейса. Это просто объясняет, что происходит. Причиной может быть предотвращение взаимоблокировок при работе с устаревшими объектами STA COM. Я не знаю, как предотвратить это.