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 , newpreparemodel
(2) started
- user changes data , clicks refresh again
preparemodel
(2) cancelled , newpreparemodel
(3) started- ..
preparemodel
(n) finishedupdateui
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
Post a Comment