user interface - Proper way how to prepare data in async cancellable workflow with responsive UI -


this question based on async.trycancelled doesn't work async.runsynchronously looks complex, cut simple part try solve.

suppose have functions:

let preparemodel () =      async {         // might take lot of time (1-50seconds)         let! = ...         let! b = ...         let! res = combine b         return res     }  let updateui model =     runonuithread model 

preparemodel prepares data should displayed user. updateui refreshes ui (removes old controls , creates new ctls based on new data).

question: how should call 2 functions preparemodel cancellable time?

the flow

  • user clicks refresh
    • preparemodel(1) started , running asynchronously, ui responsive , user can work application
  • user changes data , clicks refresh again
    • preparemodel(1) cancelled , new preparemodel(2) started
  • user changes data , clicks refresh again
    • preparemodel(2) cancelled , new preparemodel(3) started
    • ..
    • preparemodel(n) finished
    • updateui ran on ui thread, redraws ui

(my first solution based on mailboxprocessor ensures 1 preparemodel executed, see @ async.trycancelled doesn't work async.runsynchronously experimented this, it's not bug free)

one possible approach start workflow asynchronously in background using async.start (then should cancellable). redraw ui @ end, can use async.switchtocontext make sure last part of workflow executes on ui. here sketch:

// capture current synchronization context of ui // (this should run on ui thread, i.e. when starting) let synccontext = system.threading.synchronizationcontext.current  // cancellation token source used cancelling // running workflow (this can mutable) let cts = ref (new cancellationtokensource())  // workflow calculations , updates gui let updatemodel () =        async {           // might take lot of time (1-50seconds)           let! = ...           let! b = ...           let! res = combine b           // switch gui thread , update ui         do! async.switchtocontext(synccontext)         updateuserinterface res     }    // called in click handler - cancel previous // computation, creat new cancellation token & start new 1 cts.cancel() cts := new cancellationtokensource() async.start(updatemodel(), cts.token) 

Comments

Popular posts from this blog

delphi - How to convert bitmaps to video? -

jasper reports - Fixed header in Excel using JasperReports -

python - ('The SQL contains 0 parameter markers, but 50 parameters were supplied', 'HY000') or TypeError: 'tuple' object is not callable -