Как это возможно: OnPaint обрабатывается в то время как в WaitOne - PullRequest
18 голосов
/ 27 декабря 2010

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

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

alt text

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

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

Ответы [ 2 ]

21 голосов
/ 27 декабря 2010

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

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

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

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

3 голосов
/ 27 декабря 2010

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

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