.NET: Как мне вызвать делегата в конкретном потоке? (ISynchronizeInvoke, Dispatcher, AsyncOperation, SynchronizationContext и т. Д.)

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

Во-вторых, извините, если вопрос слишком длинный. Я пытаюсь собрать воедино различные фрагменты информации, плавающие здесь и там, чтобы также предоставить ценную информацию. Мой вопрос, однако, находится прямо в разделе «Что я хотел бы знать».

Моя миссия - наконец понять различные способы, предлагаемые .NET для вызова делегата в конкретном потоке.


Что я хотел бы знать:

  • Я ищу наиболее общий способ (не зависящий от Winforms или WPF) для вызова делегатов в определенных потоках.

  • Или, говоря иначе: мне было бы интересно, если и как , различные способы сделать это (например, с помощью диспетчера WPF ) используют друг друга; то есть, если есть один общий механизм для вызова делегата между потоками, который используется всеми остальными.


Что я уже знаю:

  • Есть много классов, связанных с этой темой; среди них:

    • SynchronizationContext System.Threading )
      Если бы мне пришлось угадывать, это был бы самый простой; хотя я не понимаю, что именно он делает и как он используется.

    • AsyncOperation & AsyncOperationManager System.ComponentModel )
      Кажется, быть оболочками вокруг SynchronizationContext . Не знаю, как их использовать.

    • WindowsFormsSynchronizationContext System.Windows.Forms )
      Подкласс SynchronizationContext .

    • ISynchronizeInvoke ( в System.ComponentModel )
      Используется Windows Forms. (Класс Control реализует это. Если бы мне пришлось угадывать, Я бы сказал, что эта реализация использует WindowsFormsSynchronizationContext .)

    • Dispatcher и DispatcherSynchronizationContext System.Windows.Threading )
      Похоже, что последний является еще одним подклассом SynchronizationContext , и первый делегирует ему.

  • Некоторые потоки имеют собственный цикл сообщений вместе с очередью сообщений.

    (страница MSDN О сообщениях и очередях сообщений содержит некоторую вводную справочную информацию о том, как циклы сообщений работают на системном уровне, то есть очереди сообщений в качестве Windows API.)

    Я могу увидеть, как можно реализовать вызов между потоками для потоков с очередь сообщений. Используя Windows API, вы помещаете сообщение в конкретный поток ' s очередь сообщений через PostThreadMessage , которая содержит инструкцию для вызова некоторого делегата. Цикл сообщений, который выполняется в этом потоке, в конечном итоге дойдет до этого сообщения, и будет вызван делегат.

    Из того, что я прочитал в MSDN , поток автоматически не имеет собственной очереди сообщений . Очередь сообщений станет доступной, например, когда поток создал окно. Без очереди сообщений для потока не имеет смысла иметь цикл сообщений.

    Итак, возможен ли вообще вызов делегата между потоками, когда целевой поток не имеет цикла сообщений? Скажем, в консольном приложении .NET? (Судя по ответам на этот вопрос , я полагаю, что с консольными приложениями это действительно невозможно. )

10
задан Community 23 May 2017 в 11:46
поделиться