这两个函数(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
它们可能是相同的,这取决于。
Async.SwitchToContext
将使异步延续在SynchronizationContext.Post
上运行。它发布的内容完全取决于调用doSync
的上下文。
WPF 有一个消息泵系统 - 调度程序,它在主(UI)线程上调度工作单元。
现在,postToUI
肯定会在调度程序框架上运行委托。 如果从 WPF 上下文中调用doSync
,则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
.
附言
由于Invoke
块直到返回,而SwitchToContext
实际使用Post
,因此doSync
更postToUI
,postToUI
更doSync
。