Goswin Rothenthal
Goswin Rothenthal

Reputation: 2354

F# Async.SwitchToContext vs. Dispatcher.Invoke

Are these two functions ( doSync and postToUI ) doing the same kind of evaluation on the (WPF) UI thread?

Or is there a subtle difference?

My question is less about coding style but more about what is actually happening behind the scene.

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

Upvotes: 3

Views: 193

Answers (1)

Asti
Asti

Reputation: 12687

They could be the same, it depends.

Async.SwitchToContext will make the async continuations run on SynchronizationContext.Post. What it's posting to entirely depends on the context of the call to doSync.

WPF has a message pump system - the Dispatcher, which schedules units of work on the main (the UI) thread.

Now, postToUI will certainly run the delegate on a dispatcher frame. If you call doSync from within a WPF context, SynchronizationContext.Current will be DispatcherSynchronizationContext. And under the hood:

    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);
    }

you can see that DispatcherSynchronizationContext ends up calling Dispatcher.Invoke.

So, to summarise:

  • If you are in a WPF context, doSync will call Dispatcher.BeginInvoke.
  • If you are not in a WPF context, doSync will call whatever implements Post on the current SynchronizationContext.
  • If you are in either context, postToUI will call Dispatcher.Invoke.

P.S.

Since Invoke blocks until return, and SwitchToContext actually uses Post, doSync is more postToUI, and postToUI is more doSync.

Upvotes: 1

Related Questions