正确的方法如何美元与响应性的UI异步撤销工作流程p $ ppare数据 [英] Proper way how to prepare data in async cancellable workflow with responsive UI
问题描述
这个问题是基于<一个href=\"http://stackoverflow.com/questions/9601299/async-trycancelled-doesnt-work-with-async-runsynchronously\">Async.TryCancelled不Async.RunSynchronously 看起来复杂的工作,所以我将削减一个简单的一部分,我试图解决的问题。
This question is based on Async.TryCancelled doesn't work with Async.RunSynchronously that looks complex, so I will cut a simple part that I try to solve.
假设我有这样的功能:
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
应该向用户显示
prepareModel
prepares数据。 的updateUI
刷新UI(删除旧的控制,并根据新的数据的新的CTL)。
prepareModel
prepares data that should be displayed to the user. updateUI
refreshes the UI (removes old controls and creates new ctls based on new data).
问:我应该如何拨打电话两个功能,使 prepareModel
是撤销任何时间
Question: How should I call the two functions so that prepareModel
is cancellable any time?
的流动是
- 用户点击刷新
-
prepareModel
(1)启动并正在运行的异步的,所以用户界面反应灵敏,用户可以使用应用程序
- user clicks refresh
prepareModel
(1) started and is running asynchronously, so the UI is responsive and user can work with the application
-
prepareModel
(1)被取消,
新的prepareModel
(2)启动
prepareModel
(1) from is cancelled and newprepareModel
(2) is started
-
prepareModel
(2)被取消,
新的prepareModel
(3)启动 - ..
-
prepareModel
(N)完成 -
的updateUI
是运行在UI线程,重绘UI
prepareModel
(2) is cancelled and newprepareModel
(3) is started- ..
prepareModel
(n) finishedupdateUI
is ran on UI thread, redraws the UI
的(我的第一个解决方案是基于
MailboxProcessor
,以确保只有一个prepareModel
是执行,请参阅Async.TryCancelled不Async.RunSynchronously 的工作,但因为我这个尝试,它不是无bug)的(My first solution is based on
MailboxProcessor
that ensures that only oneprepareModel
is executed, see at Async.TryCancelled doesn't work with Async.RunSynchronously but as I experimented with this, it's not bug free)推荐答案
一个可能的方法是使用异步启动工作流在后台
Async.Start
(那么它应撤销)。要在末尾重绘UI,可以使用Async.SwitchToContext
,以确保工作流程的最后一部分在UI上执行。这里是一个草图:One possible approach would be to start the workflow asynchronously in the background using
Async.Start
(then it should be cancellable). To redraw the UI at the end, you can useAsync.SwitchToContext
to make sure that the last part of the workflow executes on the UI. Here is a sketch:// 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)
这篇关于正确的方法如何美元与响应性的UI异步撤销工作流程p $ ppare数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-