ste*_*tej 1 user-interface f# asynchronous mailboxprocessor
这个问题基于Async.TryCancelled不适用于看起来很复杂的Async.RunSynchronously,因此我将剪切一个我试图解决的简单部分.
假设我有这个功能:
let prepareModel () =
async {
// this might take a lot of time (1-50seconds)
let! a = ...
let! b = ...
let! res = combine a b
return res
}
let updateUI model =
runOnUIThread model
Run Code Online (Sandbox Code Playgroud)
prepareModel准备应该向用户显示的数据.updateUI刷新UI(删除旧控件并根据新数据创建新的ctl).
问题:如何调用这两个函数以便prepareModel随时可以取消?
流程是
prepareModel(1)启动并异步运行,因此UI响应迅速,用户可以使用该应用程序prepareModel(1)取消取消,新prepareModel(2)开始prepareModel(2)取消,新prepareModel(3)开始prepareModel(n)完成了updateUI 在UI线程上运行,重绘UI(我的第一个解决方案基于MailboxProcessor确保只prepareModel执行一个,请参阅Async.TryCancelled不能与Async.RunSynchron一起使用,但是当我试验这个时,它不是没有错误的)
一种可能的方法是在后台使用异步启动工作流Async.Start(然后它应该是可取消的).要在最后重绘UI,您可以使用Async.SwitchToContext以确保工作流的最后部分在UI上执行.这是一个草图:
// Capture current synchronization context of the UI
// (this should run on the UI thread, i.e. when starting)
let syncContext = System.Threading.SynchronizationContext.Current
// Cancellation token source that is used for cancelling the
// currently running workflow (this can be mutable)
let cts = ref (new CancellationTokenSource())
// Workflow that does some calculations and then updates gui
let updateModel () =
async {
// this might take a lot of time (1-50seconds)
let! a = ...
let! b = ...
let! res = combine a b
// switch to the GUI thread and update UI
do! Async.SwitchToContext(syncContext)
updateUserInterface res
}
// This would be called in the click handler - cancel the previous
// computation, creat new cancellation token & start the new one
cts.Cancel()
cts := new CancellationTokenSource()
Async.Start(updateModel(), cts.Token)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
220 次 |
| 最近记录: |