Wpf F#Async.SwitchToContext与Dispatcher.Invoke

Wpf F#Async.SwitchToContext与Dispatcher.Invoke,wpf,asynchronous,f#,Wpf,Asynchronous,F#,这两个函数(doSync和postToUI)是否在(WPF)UI线程上执行相同的计算 还是有细微的区别 我的问题不是关于编码风格,而是关于幕后实际发生的事情 open System.Threading open System.Windows.Threading let doSync (f:'a -> 'b) x = async{ do! Async.SwitchToContext SynchronizationContext.Current retur

这两个函数(
doSync
postToUI
)是否在(WPF)UI线程上执行相同的计算

还是有细微的区别

我的问题不是关于编码风格,而是关于幕后实际发生的事情

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
开放系统线程
打开System.Windows.Threading
设doSync(f:'a->'b)x=
async{do!async.SwitchToContext SynchronizationContext.Current
返回f x
}|>Async.RunSynchronously
让postToUI:('a->'b)->'a->'b=
乐趣f x->
Dispatcher.CurrentDispatcher.Invoke(new System.Func(fun()->fx),[| |]]
|>拆开

它们可能是一样的,这要看情况而定

Async.SwitchToContext
将使异步继续在
SynchronizationContext.Post
上运行。它的发布目的完全取决于调用
doSync
的上下文

WPF有一个消息泵系统——Dispatcher,它在主(UI)线程上调度工作单元

现在,
postToUI
肯定会在dispatcher框架上运行委托。 如果从WPF上下文中调用
doSync
SynchronizationContext.Current
将是
DispatchersSynchronizationContext
。以及:

您可以看到,
DispatcherSynchronizationContext
最终调用了
Dispatcher.Invoke

因此,总结一下:

  • 如果您处于WPF上下文中,
    doSync
    将调用
    Dispatcher.BeginInvoke
  • 如果您不在WPF上下文中,
    doSync
    将调用当前服务器上的任何实现
    Post
    SynchronizationContext
  • 如果您在任一上下文中,
    postToUI
    将调用调度程序。调用
附言


由于
Invoke
阻塞直到返回,
SwitchToContext
实际上使用了
Post
doSync
更多的是
postToUI
postToUI
更多的是
doSync
,因此,在WPF中,
Post
调用也会以相同的方式阻塞,因为
异步.RunSynchronously
?是的,它是阻塞的。另一个细微的区别是,
BeginInvoke
不会立即运行,而是将其排队等待执行。
    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);
    }