Async/await with/without awaiting (fire and forget)
I'm asking this, because we're moving our app to service fabric where we no longer can use HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => await LongMethodAsync()); and the advice is to simply replace it with Task.Run.
That's bad advice. You should use a separate background process separated from your web frontend by a queue.
What's the in-depth logic behind the calls?
- Starts the asynchronous method on the current thread. Ignores all results (including exceptions).
- Starts the asynchronous method on the current thread. Asynchronously waits for it to complete. This is the standard way of calling asynchronous code.
- Starts the asynchronous method on a thread pool thread. Ignores all results (including exceptions).
- Starts the asynchronous method on a thread pool thread. Asynchronously waits for it to complete.
- Exactly the same as #3.
- Exactly the same as #4.
Fire and forget, using `Task.Run` or just calling an async method without `await`
In general especially when it comes to libraries or console apps, in order to fire and forget an async method, is it better to just call the async method without awaiting it or use Task.Run?
In general, it's best not to use fire-and-forget at all.
"Fire and forget" means:
- You don't care if the code has an exception. Any exceptions will cause it to fail silently; no logging, no notification, etc.
- You don't need to know when the code completes. I.e., the consuming application doesn't ever need to wait for the code to complete. Even during shutdown.
- You don't need the code to complete. As a corollary of (2), fire-and-forget code may not run to completion; and as a corollary of (1), you would have no notification that it failed to complete.
In short, "fire and forget" is only appropriate for an extremely small number of tasks. E.g., updating a cache. I'd say probably 85% or more of "fire and forget" code is wrong - it's using fire and forget for code that should not be fire and forget.
So I'd say the best solution is to not use fire and forget at all. At the very least, you should expose a Task
somewhere that represents a "followup action". Consider adding the Task
to your return type or exposing it as a property.
Adopting fire and forget - especially in a library - means you're forcing all consumers to never know when it's safe to shut down and exit. But if you really want to do fire and forget, there are a few options.
A. One option is calling an async void
function without a context. The consuming application still has no way to determine if/when the code completes, but at least that way exceptions are not ignored.
B. Another option is to start the task without a context. This option has both disadvantages of fire and forget code: exceptions are ignored and the calling code cannot know when it completes.
Both of these recommendations start the task without a context. There are helpers for doing this, or you can wrap the call in Task.Run
(slightly less efficient, but it works fine).
I wouldn't recommend starting the task directly. While this would work fine in a Console app, it's not appropriate for libraries which may be called in situations where a context is provided.
Fire and Forget Async Await Call
It's just a warning, so that you know it's not been await
ed on. You can use discard to make it clear you don't care whether or not it ends up running to completion:
_ = SendSMS();
So, question is, If the UserRegistration() method returns before completion of SendSMS() OR SendEmail(), Does it fire the exception?
Nope.
And Is it good practice to make Fire and Forget call in Async Await Methods?
Not in my opinion.
Non awaitable as fire & forget - is it safe to use?
I don't to use Task.Run for this kind of operation, because it's bad.
It's important to recognize/specify context for this kind of statement. Task.Run
is bad on ASP.NET. It's perfectly OK to use in a GUI app on the client side.
We need to write some logs in our code.
I strongly recommend using an established logging library. Most of them work by using an in-memory queue that is (synchronously) written to by your code, and which is continually processed by a background thread. This is a pattern that is well-established.
Is it a viable solution for logging in a "fire-and-forget" mode?
One of the problems with "fire and forget" is that you don't know when there are errors. The established logging libraries all have some kind of system for dealing with errors communicating with the logging backend; the code you posted will just ignore them.
What if I create objects inside this inline method, when are they going to be GC'ed?
Conceptually, async methods act as GC "roots" as long as they are going to continue executing in the future. So local objects will be GC'ed when the method completes.
Fire-and-forget with async vs old async delegate
Avoid async void
. It has tricky semantics around error handling; I know some people call it "fire and forget" but I usually use the phrase "fire and crash".
The question is: Given a synchronous method A(), how can I call it asynchronously using async/await in a fire-and-forget manner without getting a solution that is more complicated than the "old way"
You don't need async
/ await
. Just call it like this:
Task.Run(A);
Using await on async method that returns only Task
During the execution, there were no unwanted consequences whatsoever.
I disagree. The resulting code is dangerous. ASP.NET pre-Core was able to detect similar situations and throw an exception ("An asynchronous module or handler completed while an asynchronous operation was still pending"). For technical reasons, ASP.NET Core cannot detect this situation so you don't get that "safety net" exception, but the situation itself is still just as bad.
The thing is, Visual Studio generates no warning message either when such thing happens
You don't get CS4014 ("Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the await operator to the result of the call.")?
is there actually any danger present of lefting out the await in such cases? I know that await should be applied on every async method naturally, but I don't really understand the reasons behind this when caller practically has no return value to use. Perhaps something with catching exceptions?
Yes, there are dangers. Task
(even without a result type) is used for two things: for the caller to know when the operation completes, and for the caller to detect exceptions from that operation.
So, the one issue is that exceptions are silently swallowed. More specifically, exceptions from the async
method are captured by the async
state machine and placed on the returned Task
, which is then ignored.
if I handle the exceptions in the said methods themselves (the ones not properly awaited), could we then say that all is fine and well?
No, because the other issue still exists: the caller doesn't know when the asynchronous operation completes. This is particularly important to know in ASP.NET, because the result should not be sent until the operation is complete. Any kind of "fire and forget" code on ASP.NET lives outside the request/response lifetime; i.e., it's request-extrinsic code.
I go into some detail on my blog about why request-extrinsic code is dangerous. In summary, your ASP.NET handler may complete too soon, and in that case, the request-extrinsic code may get "lost". At the very least, whatever it's doing won't be done by the time the response is sent; and in the case of a regular shutdown (e.g., rolling upgrades), it might not get done at all.
Run a async function without waiting for the response in c# webforms (fire and forget)
How do I make this truly async?
In ASP.NET, await
yields to the thread pool, not the client.
If possible, I recommend changing the client so that a longer request is handled appropriately; e.g., calling this via JavaScript instead of a click handler, and updating the page when it completes.
If you really need to return early from an web request, then you should implement a basic distributed architecture. As described on my blog, this consists of two parts:
- A durable queue of work.
- A backend processor of that queue.
Should async method always call await, if not what is the implication?
Should async method always call await, if not what is the implication?
As I describe on my blog, async
methods always begin executing synchronously, just like any other methods. await
is where things may get asynchronous.
If a code path is taken where there is no await
(or if the tasks awaited are already completed), then the method completes synchronously and returns an already-completed task to its caller. This is not a problem in practice, because "*Async" means "may be asynchronous", not "must be asynchronous".
In this specific example, you're using async void
, but if this was an async Task
method that was called a lot, in that case I'd recommend considering returning ValueTask
instead, which would save some memory allocation for the Task
whenever it completes synchronously.
Related Topics
How to Programmatically Generate Keypress Events in C#
How to Abort a Task Like Aborting a Thread (Thread.Abort Method)
ASP.NET 5:Is the "Dotnet" Command Replacing "Dnu" and "Dnx" Commands
How to Write a JSON File in C#
Easiest Way to Parse JSON Response
How to Use Visual Studio Code to Develop Unity3D Projects in Ubuntu
How to Create a Simple Proxy in C#
How to Create a .Net Datetime from Iso 8601 Format
Identifying Last Loop When Using for Each
How to Set Cursor Position in Gtk -Linux, Monodevelop
Byte Array to Image Conversion
Mono Shared Library Under Linux Location
Run Async Method Regularly with Specified Interval