Is there a way to instruct F# to always use threadpool threads for continuations in async computation expressions regardless of the synchronization context?
Sure you use Async.SwitchToThreadPool or another Switch... method
like this:
async {
do! Async.SwitchToThreadPool ()
// ... your other stuff
}
Related
I have a confusion in understanding Dart's async/await functionality. Most tutorials use the following example:
Future<String> createOrderMessage() async {
var order = await fetchUserOrder();
return 'Your order is: $order';
}
Future<String> fetchUserOrder() =>
// Imagine that this function is
// more complex and slow.
Future.delayed(
const Duration(seconds: 2),
() => 'Large Latte',
);
Future<void> main() async {
print('Fetching user order...');
print(await createOrderMessage());
}
I understand that the fetchUserOrder function returns a Future. Anyone who calls this function will immediately get a Future object as a result but this Future object may not have the real result value at that time. It will be filled up in "future".
Now, the createOrderMessage function calls: await fetchUserOrder(); This means, the control will wait till fetchUserOrder() returns a completed/non-empty Future. Am I right here? Is this what await does?
If that is correct, it means, the createOrderMessage function is essentially synchronous now because it won't return until the Future returned by fetchUserOrder is filled. Thus, the order variable in this function is initialized with a completed Future. Then why does this function need the "async" keyword in its function declaration? What does it signify?
Second confusion is if Dart is single threaded, when and how exactly is an async function executed? If I invoke multiple method calls that return Futures like this without await:
...
Future<A> fa = getA();
Future<B> fb = getB();
Future<C> fa = getC();
...
Will the functions getA, getB, and getC be executed sequentially in the background or they will be executed "in parallel" somehow?
Now, the createOrderMessage function calls: await fetchUserOrder(); This means, the control will wait till fetchUserOrder() returns a completed/non-empty Future. Am I right here? Is this what await does?
Yes. the await keyword means you get the completed T instead of Future<T> in return. So:
var a = fetchUserOrder(); // Type of a: Future<String>
var b = await fetchUserOrder(); // Type of b: String
When you use await, you tell the code to await the completion of the process and get the actual result. But without await, the stream is in the future and is in process until you await it somewhere else.
why does this function need the "async" keyword in its function declaration?
It's a rule to specify long-running functions. So when a function awaits for a long running process to complete, the function itself is also a long-running process. Why? Because it's waiting for another one to complete.
Therefore, you need to specify async for that as well. When another function is calling this one, it also knows this one might be long-running.
In short, every awaitable function needs to be in an async function.
Second confusion is if Dart is single threaded, when and how exactly is an async function executed?
You're mixing the concept of parallelism with asynchronous. An async process does not have to be done in multi thread.
Async processes can be one one at time, but in a different order in compare to synchronous code.
Take a look at this article which explains asynchronous in a single thread.
Now, the createOrderMessage function calls: await fetchUserOrder(); This means, the control will wait till fetchUserOrder() returns a completed/non-empty Future. Am I right here? Is this what await does?
If that is correct, it means, the createOrderMessage function is essentially synchronous now because it won't return until the Future returned by fetchUserOrder is filled. Thus, the order variable in this function is initialized with a completed Future.
await allows asynchronous functions to have the appearance of synchronous functions by allowing asynchronous code to be structured very similarly to synchronous code. In your example, it's syntactic sugar for registering a Future.then() callback and immediately returning:
Future<String> createOrderMessage() {
var future = fetchUserOrder().then((order) {
return 'Your order is: $order';
});
return future;
}
await defers execution of the rest of that function; it does not wait and block execution of your entire thread. Your program will continue running its event loop, possibly allowing other asynchronous operations to make progress.
Will the functions getA, getB, and getC be executed sequentially in the background or they will be executed "in parallel" somehow?
As I mentioned in comments, it depends on how getA, getB, and getC are implemented. They could run in parallel, such as if they run in separate Dart isolates or in separate threads in the Dart VM/runtime.
I am trying out the Future with async await for asynchronous programming.
The code i tested is a simple Future.
//order a new coffee perhaps!
Future<String> order(String newOrder){
final String Function() func = ()=> "${newOrder} is requested!";
final _order = Future.delayed(Duration(seconds: 5),func);
return _order;
}
When i run this code like a promise.
order("promised order")
.then((result) => print(result))
.catchError((err){
print(err.error);
});
This behaves like a asynchronous non-blocking code
However the same code when i run it with async/await behaves like a synchronous code and blocks all the other code, it waits 5 secs to run the next line.
void main(List<String> arguments) async {
final _myOrder = await order('Lattee mocha');
print(_myOrder);
//...all the other code waits for
}
So i thought async/await is same as futures, where non-blocking..
How come it blocks the other code execution ?
The whole point of the async/await pattern is to wait (hence await) until the Future completes and only then continue with this code execution.
Think of it as a way to not have endless .then() chains and much simplified error handling.
If you want to not wait, then you just leave out the await keyword. Obviously, if you don't (a)wait, you don't get the result.
You can still use classic .then() chains when it suits your purpose better in your program.
What people talk about when they say "non blocking" they mean that when the compiler sees the await keyword, it knows to keep the rest of the program, the event loops, animations etc running and not block the complete program.
let CreateEventSourcingConnection() =
task {
let connection =
let ipEndPoint = IPEndPoint(IPAddress.Loopback, 1113)
EventStoreConnection.Create(ipEndlPoint)
do! connection.ConnectAsync()
return connection
}
For task I get:
The value of constructor 'task' is not defined.
So, what is this and how can I define it?
I assume that the question is in the context of Logary, which gets the task computation builder from the TaskBuilder.fs NuGet package (as we can see from Paket references). The TaskBuilder.fs project is available here with some documentation.
So, task is a variable that represents an instance of the TaskBuilder computation builder. This is an F# computation expression, which lets you create computations that create the .NET Task<T> type as the result. Inside the computation expression, you can use let! and do! for the same purpose as await in C#, that is for waiting until some asynchronous operation completes (without blocking a thread):
task {
do! Console.Out.WriteLineAsync("Enter a filename:")
let! name = Console.In.ReadLineAsync()
use file = File.CreateText(name)
for i in Enumerable.Range(0, 100) do
do! file.WriteLineAsync(String.Format("hello {0}", i))
do! Console.Out.WriteLineAsync("Done")
return name
}
Here, WriteLineAsync and ReadLineAsync are .NET methods that return Task and we can use them as if they were returning just string or unit.
It is also worth adding that Logary is perhaps not the easiest piece of F# code to look into. It is very clever and nice, but relies on the HOPAC concurrency library which requires a fair bit of background knowledge and uses a number of fancy operators, which can make code quite tricky to understand. So if you are relatively new to F#, understanding HOPAC code might be a bit of a struggle!
I was wondering what would be the equivalent of the C# async main in F#. More to the point, is there a special way of consuming/using async methods from main in an F# program or is it just a matter of waiting for completion?
To be more concrete, say we are using the .NET Core Generic Host.
In a C# program, main might look like this:
class Program
{
static async Task Main(string[] args)
{
await new HostBuilder().Build().RunAsync();
}
}
In an F# program, my instinct would be to do something like this:
[<EntryPoint>]
let main args =
HostBuilder().Build.RunAsync().Wait()
...or...
[<EntryPoint>]
let main args =
HostBuilder().Build.RunAsync() |> Async.AwaitTask |> Async.RunSynchronously
...or...
[<EntryPoint>]
let main args =
async {
return HostBuilder().Build.RunAsync() |> Async.AwaitTask
} |> Async.RunSynchronously
...or just avoid async...but that's no fun...
[<EntryPoint>]
let main args =
HostBuilder().Build.Run()
There are a few more formulations I could show but I think these make the point.
I imagine that part of the answer lies in answering these other questions
"what does it mean to run an async main method" and
"what's the point of making main async?"
Going by examples, async main seems mostly to be about making it possible for other places to call main in an async way (in those cases where main is not really "main", ie. unit testing, etc).
In the case of F#, I imagine there are at least 2 things preventing one from just returning an Async computation from main:
The EntryPointAttribute that enforces an int return type for status codes...right?
The compiler probably is not prepared to handle the async computation as the exit value of the program...right?
AFAIK there's no async main equivalent in F#.
If you look at C# implementation behind the scenes it looks like this:
private static void <Main>(string[] args)
{
Program.Main(args).GetAwaiter().GetResult();
}
Program.Main is the async main.
Personally I find this pattern slightly scary depending on what SynchronizationContext is used.
To emulate async main I would:
let theAsyncTask : Async<int> = ...
[<EntryPoint>]
let main argv =
async {
do! Async.SwitchToThreadPool ()
return! theAsyncTask
} |> Async.RunSynchronously
theAsyncTask is the actual work to be done, the embedded async switches to the thread pool so that the main thread can safely block and await the result.
In C# awaiting the task awaiter is or ConfiguredTaskAwaitable is quite easy - just use await. What is the alternative for F#?
let! result = ...? doSomething().ConfigureAwait(false) ...?
F# async workflows and C# async-await keywords are two entirely separate mechanisms, and as such they are not directly compatible (though no doubt you can have wrappers that make that possible and most likely there are already wrappers like this around).
If you want to combine tasks with F# async workflow, you'd use the actual tasks rather than awaiters:
let! result = Async.AwaitTask task
If you have an API that gives you awaiters rather than tasks, here's a heavy-handed attempt at making an async out of a TaskAwaiter<'T>:
module Async =
let fromTaskAwaiter (awaiter: TaskAwaiter<'a>) =
async {
use handle = new SemaphoreSlim(0)
awaiter.OnCompleted(fun () -> ignore (handle.Release()))
let! _ = handle.AvailableWaitHandle |> Async.AwaitWaitHandle
return awaiter.GetResult()
}