F # Asyn c .SwitchToContext vs. Dispatcher.Invoke - PullRequest
2 голосов
/ 15 апреля 2020

Эти две функции (doSync и postToUI) выполняют одинаковые оценки в потоке пользовательского интерфейса (WPF)?

Или есть небольшая разница?

Мой Вопрос не столько в стиле кодирования, сколько в том, что на самом деле происходит за кулисами.

open System.Threading
open System.Windows.Threading

let doSync (f:'a -> 'b) x = 
    async{  do! Async.SwitchToContext SynchronizationContext.Current
            return f x
         } |> Async.RunSynchronously


let postToUI : ('a -> 'b) -> 'a -> 'b =
    fun f x ->
      Dispatcher.CurrentDispatcher.Invoke(new System.Func<_>(fun () -> f x), [||])      
      |> unbox

1 Ответ

1 голос
/ 15 апреля 2020

Они могут быть одинаковыми, это зависит.

Async.SwitchToContext заставит асинхронные c продолжения работать на SynchronizationContext.Post. То, что он публикует, полностью зависит от контекста вызова doSync.

. В WPF имеется система обработки сообщений - диспетчер, который планирует единицы работы в основном потоке (пользовательском интерфейсе).

Теперь postToUI непременно выполнит делегат в кадре диспетчера. Если вы позвоните doSync из контекста WPF, SynchronizationContext.Current будет DispatcherSynchronizationContext. И под капотом :

    public override void Send(SendOrPostCallback d, Object state)
    {
       _dispatcher.Invoke(DispatcherPriority.Send, d, state);         
    }

    public override void Post(SendOrPostCallback d, Object state)
    {
        _dispatcher.BeginInvoke(_priority, d, state);
    }

вы можете видеть, что DispatcherSynchronizationContext в итоге вызывает Dispatcher.Invoke.

Итак, подведем итог:

  • Если вы находитесь в контексте WPF, doSync вызовет Dispatcher.BeginInvoke.
  • Если вы не находитесь в контексте WPF, doSync будет вызывать любые реализации Post для текущего SynchronizationContext.
  • Если вы находитесь в каком-либо контексте, postToUI вызовет Dispatcher.Invoke.

PS

С Invoke блоки до возврата и SwitchToContext фактически использует Post, doSync больше postToUI и postToUI больше doSync.

...