正确的方法如何美元与响应性的UI异步撤销工作流程p $ ppare数据 [英] Proper way how to prepare data in async cancellable workflow with responsive UI

查看:143
本文介绍了正确的方法如何美元与响应性的UI异步撤销工作流程p $ ppare数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是基于<一个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 new prepareModel(2) is started

      • prepareModel (2)被取消,
        新的 prepareModel (3)启动

      • ..

      • prepareModel (N)完成

      • 的updateUI 是运行在UI线程,重绘UI

      • prepareModel(2) is cancelled and new prepareModel(3) is started
      • ..
      • prepareModel(n) finished
      • updateUI 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 one prepareModel 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 use Async.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆