To execute operations on a background thread and avoid blocking the UI in a WPF application, I often find myself writing this pattern:
async {
// some code on the UI thread
let uiThread = SynchronizationContext.Current
do! Async.SwitchToThreadPool()
let! result = // some Async<'t>
do! Async.SwitchToContext uiThread
// do things with the result if it wasn't () all along
}
Async
functions appears to do something like that.If not, does it make sense to just turn the above code into a function?
let onThreadPool operation =
async {
let context = SynchronizationContext.Current
do! Async.SwitchToThreadPool()
let! result = operation
do! Async.SwitchToContext context
return result
}
That adds another level of async { }
nesting - can this cause issues at "some" point?
What you're doing here definitely makes sense. One useful operation here is Async.StartImmediate
, which starts the async workflow on the current thread. If you call this from the UI thread, this guarantees that the workflow will also start on the UI thread and so you can capture the synchronization context inside the workflow.
The other trick is that many built-in asynchronous F# operations automatically jump back to the original synchronization context (those that are created using Async.FromContinuations
, including e.g. AsyncDownloadString
), so when you're calling one of those, you do not even need to explicitly jump back to the original synchronization context.
But for other asynchronous operations (and for non-async operations that you want to run in the background), your onThreadPool
function looks like a great way of doing this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With