7

I am using a library which has been written in C# and uses the async/await pattern. In C# I can await something by calling it with ConfigureAwait(false) but when I use the library from F# I don't see a way of doing the same thing?

Currently I do SomeMethodAsync() |> Async.AwaitTask to convert it into an Async F# workflow, but how can I do the same as ConfigureAwait(false) from F# as well when calling SomeMethodAsync?


EDIT:

With some awesome help in the F# Slack channel and some additional googling I found a good explanation of how to switch context here: http://tomasp.net/blog/async-non-blocking-gui.aspx/

dustinmoris
  • 3,195
  • 3
  • 25
  • 33
  • Why exactly do you want to not continue on captured context? What's the larger problem? – Fyodor Soikin Jun 30 '16 at 17:32
  • 2
    It is good practice for library code as far as I understand. This explains is well: http://stackoverflow.com/questions/14526377/why-does-this-async-action-hang – dustinmoris Jun 30 '16 at 17:35
  • Doesn't `SomeMethodAsync().ConfigureAwait(false) |> Async.AwaitTask` work for you? – Fyodor Soikin Jun 30 '16 at 18:00
  • No unfortunately not, because ConfigureAwait(false) returns an awaitable instead of a task – dustinmoris Jun 30 '16 at 18:10
  • 1
    Actually I found the solution. Someone pointed me to this: http://tomasp.net/blog/async-non-blocking-gui.aspx/ – dustinmoris Jun 30 '16 at 18:10
  • 5
    you can post that solution as answer and accept it :) – niceman Jun 30 '16 at 20:12
  • There is nothing relevant in Petricek's blog post that I can see. Are you confusing `await` with `ConfigureAwait` perhaps? Awaiting is done with `await`, *not* with `ConfigureAwait`. ConfigureAwait controls whether the original synchronization context is restored or not. It's just a function accapting a Task and returning another. You can call it just like any other function – Panagiotis Kanavos Jul 01 '16 at 08:32
  • @PanagiotisKanavos My understanding is that ConfigureAwait let's me control if it should synchronise back to the UI thread or not and Petricek has described the same thing by using `SwitchToThreadPool` in F#. Is this right or am I missing something? At least his solution seems to have fixed my issue that I had. – dustinmoris Jul 01 '16 at 10:43
  • @dustinmoris, if you found the answer, please post it below as an answer. It could be helpful to other people besides just you. Me, for instance, who came here looking for the answer to this same question. – Ryan Lundy Apr 30 '19 at 10:51

1 Answers1

2

It's as simple as calling ConfigureAwait before converting it to an F# Task.

SomeMethodAsync().ConfigureAwait(false) |>  Async.AwaitTask

However, if you are mostly dealing with C# async tasks. It's cleaner to us the TaskBuilder.fs computational expression. Available in nuget using dotnet add package TaskBuilder.fs.

You don't have to manually call ConfigureAwait(false) instead just

open FSharp.Control.Tasks.V2.ContextInsensitive

And then every time you let! it will automatically be .ConfigureAwait(false)

jbtule
  • 31,383
  • 12
  • 95
  • 128