Re[3]: Как выполнить метод в другом (основном) потоке?
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 13.07.09 12:59
Оценка: 61 (2) +1
Здравствуйте, Аноним, Вы писали:

А> Да, действительно, проверил. Если AsyncOperation создается в потоке, который является потоком UI, то все работает как описано. Если же этот поток не является потоком UI, то при вызове Post метод по факту выполняется в новом, отдельном потоке.

А> А в чем принципиальное различие между потоком UI и обычным потоком? Ведь UI-поток — это тоже обычный поток, в котором, как я понимаю, что-то докручено, чтобы работал механизм с AsyncOperation. Можно ли это "что-то" докрутить в произвольный поток?

Самый простой способ реализовать межпоточное взаимодействие явно с помощью разделяемых переменных и средств синхронизации типа ManualResetEvent, AutoResetEvent или других средств.
По поводу потоков пользовательского интерфейса: поток, работающий с UI нельзя назвать обычным.
Вот, что пишет Рихтер:

Создавая какой-либо поток, система предполагает, что он не будет иметь отношения к поддержке пользовательского интерфейса. Это позволяет уменьшить объем выделяемых ему системных ресурсов. Но, как только поток обратится к той или иной GUI-функции (например, для проверки очереди сообщений или создания окна), система автоматически выделит ему дополнительные ресурсы, необходимые для выполнения задач, связанных с пользовательским интерфейсом А если конкретнее, то система создает структуру THREADINFO и сопоставляет ее с этим потоком.

THREADINFO — это внутренняя (недокументированная) структура, идентифицирующая очередь асинхронных сообщений потока (posted-message queue), очередь синхронных сообщений потока (sent-message queue), очередь ответных сообщений (reply-message queue), оче редь виртуального ввода (virtualized input queue) и флаги пробуждения (wakc flags), она также включает ряд других переменных-членов, характеризующих локальное состояние ввода для данного потока.

Когда с потоком связывается структура THREADINFO, он получает свой набор очередей сообщений. Если процесс создает три потока и все они вызывают функцию Create Window, то и наборов очередей сообщений будет тоже три Сообщения ставятся в очередь асинхронных сообщений вызовом функции PostMessage:

BOOL PostMessage( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

При вызове этой функции система определяет, каким потоком создано окно, идентифицируемое параметром hwnd, Далее система выделяет блок пямяти, сохраняет в нем параметры сообщения и записывает этот блок в очередь асинхронных сообще ний данного потока. Кроме того, функция устанавливает флаг пробуждения QS_POST MESSAGE (о нем — чуть позже). Возврат из PostMessage происходит сразу после того, как сообщение поставлено в очередь, поэтому вызывающий поток остается в неведе нии, обработано ли оно процедурой соответствующего окна На самом деле вполне вероятно, что окно даже не получит это сообщение Такое возможно, если поток, создавший это окно, завершится до того, как обработает все сообщения из своей очереди.


Класс SyncronizationContext (точнее WindowsFormsSynchronizationContext) как раз и использует механизм отправки оконных сообщений для вызова произвольного метода в родном потоке пользовательского интерфейса.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.