Как реализован Invoke в WinForms?
От: v_0ver Россия  
Дата: 03.09.14 07:48
Оценка:
Есть ПО для которого пишется расширение(COM). Дёргать API этого ПО можно только из его потока(если поток придержать, то ПО повисает и не отвечает), то есть потока который он выделил при загрузки расширения. Так же осуществляется связь этого расширения по средствам WCF со сторонней программой.
На текущий момент сделаны костыли в виде WinForms invoke():

В Parent Thread создаётся Form, а из WCF Thread дёргается его Invoke().

Как я понимаю Invoke отправляет сообщение в пул сообщений главного цикла WinForms, а тот в свою очередь дёргает соответствующую функцию. Только не понятно каким образом WinForms прописывается в главный цикл обработки сообщений ПО?
Отредактировано 03.09.2014 7:50 v_0ver . Предыдущая версия .
Re: Как реализован Invoke в WinForms?
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 03.09.14 08:05
Оценка:
Здравствуйте, v_0ver, Вы писали:

_>Есть ПО для которого пишется расширение(COM). Дёргать API этого ПО можно только из его потока(если поток придержать, то ПО повисает и не отвечает), то есть потока который он выделил при загрузки расширения. Так же осуществляется связь этого расширения по средствам WCF со сторонней программой.

_>На текущий момент сделаны костыли в виде WinForms invoke():
_>Image: vhuiwl.png
_>В Parent Thread создаётся Form, а из WCF Thread дёргается его Invoke().

_>Как я понимаю Invoke отправляет сообщение в пул сообщений главного цикла WinForms, а тот в свою очередь дёргает соответствующую функцию. Только не понятно каким образом WinForms прописывается в главный цикл обработки сообщений ПО?


Если речь про Control.Invoke- то в конце концов зовется

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool PostMessage(HandleRef hwnd, int msg, IntPtr wparam, IntPtr lparam);

Это легко установить при помощи любого дизассемблера
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re[2]: Как реализован Invoke в WinForms?
От: v_0ver Россия  
Дата: 03.09.14 08:18
Оценка:
Здравствуйте, Sshur, Вы писали:

S>Здравствуйте, v_0ver, Вы писали:


_>>Есть ПО для которого пишется расширение(COM). Дёргать API этого ПО можно только из его потока(если поток придержать, то ПО повисает и не отвечает), то есть потока который он выделил при загрузки расширения. Так же осуществляется связь этого расширения по средствам WCF со сторонней программой.

_>>На текущий момент сделаны костыли в виде WinForms invoke():
_>>Image: vhuiwl.png
_>>В Parent Thread создаётся Form, а из WCF Thread дёргается его Invoke().

_>>Как я понимаю Invoke отправляет сообщение в пул сообщений главного цикла WinForms, а тот в свою очередь дёргает соответствующую функцию. Только не понятно каким образом WinForms прописывается в главный цикл обработки сообщений ПО?


S>Если речь про Control.Invoke- то в конце концов зовется


S>[DllImport("user32.dll", CharSet = CharSet.Auto)]

S>public static extern bool PostMessage(HandleRef hwnd, int msg, IntPtr wparam, IntPtr lparam);

S>Это легко установить при помощи любого дизассемблера


Это понятно, что вызывается PostMessage(), меня интересует каким образом уживаются 2 цикла обработки сообщений в одной нити.
Re[3]: Как реализован Invoke в WinForms?
От: catbert  
Дата: 03.09.14 08:59
Оценка: 1 (1) +1
Здравствуйте, v_0ver, Вы писали:

_>Это понятно, что вызывается PostMessage(), меня интересует каким образом уживаются 2 цикла обработки сообщений в одной нити.


В общую, единственную, очередь сообщений потока добавляется кастомное сообщение "..._ThreadCallbackMessage". В коде обработки из сообщения достается коллбек и вызывается. Вот и все.
Re: Как реализован Invoke в WinForms?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 03.09.14 09:56
Оценка: +2
Здравствуйте, v_0ver, Вы писали:

_>Только не понятно каким образом WinForms прописывается в главный цикл обработки сообщений ПО?


Что значит прописывается? Он его сам и выполняет. Application.Run это оно и есть.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[4]: Как реализован Invoke в WinForms?
От: v_0ver Россия  
Дата: 03.09.14 13:00
Оценка:
Здравствуйте, catbert, Вы писали:

C>Здравствуйте, v_0ver, Вы писали:


_>>Это понятно, что вызывается PostMessage(), меня интересует каким образом уживаются 2 цикла обработки сообщений в одной нити.


C>В общую, единственную, очередь сообщений потока добавляется кастомное сообщение "..._ThreadCallbackMessage". В коде обработки из сообщения достается коллбек и вызывается. Вот и все.


В коде обработки оно "руками" обрабатывается или это происходит прозрачно?

Я нашёл пример с SendMessageCallback и он только работает если я отправляю сообщение из той же нити где крутится главный цикл.
На MSDN написано:

If the target window belongs to a different thread from the caller, then the callback function is called only when the thread that called SendMessageCallback also calls GetMessage, PeekMessage, or WaitMessage.

Из чего следует, что вызвать калбек из потока отличного потоку обработчика сообщений нельзя?
Re[5]: Как реализован Invoke в WinForms?
От: catbert  
Дата: 04.09.14 19:57
Оценка:
Здравствуйте, v_0ver, Вы писали:

_>В коде обработки оно "руками" обрабатывается или это происходит прозрачно?


Руками, почти без unmanaged-кода.

Давайте посмотрим в сорцы. Вот код, вызываемый методами Invoke/BeginInvoke:

http://referencesource.microsoft.com/#System.Windows.Forms/ndp/fx/src/winforms/Managed/System/WinForms/Control.cs#7602

Он довольно простой. Вот что там делается:

  1. Создается и добавляется в обычную .NET-очередь некий ThreadMethodEntry (TME), который содержит обычный .NET-делегат, вейт-сигнал и какой-то контекст.
  2. Если мы в UI-потоке, просто выполняем все TME из очереди.
  3. Иначе, мы вызываем WinAPI-шный PostMessage с кастомным сообщением WindowsForms12_ThreadCallbackMessage, вообще без каких-либо параметров.
  4. В случае синхронного вызова (Invoke), мы ждем вейт-сигнал из TME, созданного в шаге 1.

Сообщения обрабатываются в методе Control.WndProc:

http://referencesource.microsoft.com/#System.Windows.Forms/ndp/fx/src/winforms/Managed/System/WinForms/Control.cs#13713

Это большой свитч, в котором сначала обрабатываются все виндовые месседжи. После этого, просто выполняются все TME из очереди.

Вот и все, никакой магии, кроме PostMessage.
Re: Как реализован Invoke в WinForms?
От: TK Лес кывт.рф
Дата: 06.09.14 14:27
Оценка:
Здравствуйте, v_0ver, Вы писали:

_>Как я понимаю Invoke отправляет сообщение в пул сообщений главного цикла WinForms, а тот в свою очередь дёргает соответствующую функцию. Только не понятно каким образом WinForms прописывается в главный цикл обработки сообщений ПО?


Сообщение в Control.Invoke отправляется окну — а кто реализует цикл выборки сообщений не суть важно.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Как реализован Invoke в WinForms?
От: bazis1 Канада  
Дата: 06.09.14 16:29
Оценка:
Здравствуйте, v_0ver, Вы писали:

_>Как я понимаю Invoke отправляет сообщение в пул сообщений главного цикла WinForms, а тот в свою очередь дёргает соответствующую функцию. Только не понятно каким образом WinForms прописывается в главный цикл обработки сообщений ПО?

PostMessage, PostThreadMessage, например. Главный цикл реализуется внутри WinForms и знает, как все обрабатывать.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.