要在后台线程上执行操作并避免阻止WPF应用程序中的UI,我经常会发现自己编写这种模式:
async {
// some code on the UI thread
let uiThread = SynchronizationContext.Current
do! Async.SwitchToThreadPool()
let! result = // some Async<'t>
do! Async.SwitchToContext uiThread
// do things with the result if it wasn't () all along
}
Async
函数似乎都没有这样做。如果没有,将上述代码转换为函数是否有意义?
let onThreadPool operation =
async {
let context = SynchronizationContext.Current
do! Async.SwitchToThreadPool()
let! result = operation
do! Async.SwitchToContext context
return result
}
这增加了async { }
嵌套的另一个级别 - 这会导致“某些”问题吗?
答案 0 :(得分:3)
你在这里所做的一切都是有道理的。这里有一个有用的操作是Async.StartImmediate
,它在当前线程上启动异步工作流。如果从UI线程调用此方法,则可以保证工作流也将在UI线程上启动,因此您可以捕获工作流内的同步上下文。
另一个技巧是许多内置异步F#操作会自动跳回到原始同步上下文(使用Async.FromContinuations
创建的那些上下文,包括例如AsyncDownloadString
),所以当你打电话时其中之一,您甚至不需要显式跳回原始同步上下文。
但对于其他异步操作(以及您希望在后台运行的非异步操作),您的onThreadPool
函数看起来是一种很好的方法。