Problem
This isn’t a copy of “How to call an async method safely in C# without await.”
What’s the best way to hide the following warning?
A simple example:
static async Task WorkAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done!");
}
static async Task StartWorkAsync()
{
WorkAsync(); // I want fire-and-forget
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
I tried these things and didn’t care for them:
static async Task StartWorkAsync()
{
#pragma warning disable 4014
WorkAsync(); // I want fire-and-forget here
#pragma warning restore 4014
// ...
}
static async Task StartWorkAsync()
{
var ignoreMe = WorkAsync(); // I want fire-and-forget here
// ...
}
Since the initial accepted response was updated, I’ve revised the accepted solution to one that uses C# 7.0 discards, as I don’t believe ContinueWith is appropriate here. I use a more complicated technique described by Stephen Cleary here whenever I need to log exceptions for fire-and-forget procedures.
Asked by noseratio
Solution #1
Discards are now available in C# 7:
_ = WorkAsync();
Answered by Anthony Wieser
Solution #2
You can prevent the warning by writing an extension method. You can leave the extension method empty or use to add exception handling. There’s a function called ContinueWith() there.
static class TaskExtensions
{
public static void Forget(this Task task)
{
task.ContinueWith(
t => { WriteLog(t.Exception); },
TaskContinuationOptions.OnlyOnFaulted);
}
}
public async Task StartWorkAsync()
{
this.WorkAsync().Forget();
}
However, because ASP.NET keeps track of how many tasks are running, it will not function with the simple Forget() extension stated above and instead throw an exception:
It can be handled with HostingEnvironment in.NET 4.5.2. QueueBackgroundWorkItem:
public static Task HandleFault(this Task task, CancellationToken cancelToken)
{
return task.ContinueWith(
t => { WriteLog(t.Exception); },
cancelToken,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.Default);
}
public async Task StartWorkAsync()
{
System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(
cancelToken => this.WorkAsync().HandleFault(cancelToken));
}
Answered by Knaģis
Solution #3
This is one of my two options for dealing with it.
(C# 7) Save it to a throwaway variable.
Example
denotes a task. DoMyStuff() => Run(() => DoMyStuff() => Run(() => DoMyStuff ConfigureAwait(false);
I now feel this to be preferable to suppressing the warning after the introduction of discards in C# 7. Because it not only silences the warning, but also makes the intention to burn and forget plain.
Furthermore, in release mode, the compiler will be able to optimize it.
Just suppress it
#pragma warning disable 4014
...
#pragma warning restore 4014
“Fire and forget” is a nice enough option.
This warning exists because, in many circumstances, it is not your purpose to use a method that returns a task without first waiting for it to complete. When you do intend to shoot and forget, it makes logical to turn off the warning.
Allow Visual Studio to add #pragma warning disable 4014 for you if you can’t remember how to spell it. To open “Quick Actions,” type Ctrl+., then “Suppress CS2014.”
All in all
It’s a waste of time to write a method that takes a few extra ticks to execute only to suppress a warning.
Answered by fjch1997
Solution #4
The following attribute can be used to enhance the method:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Await.Warning", "CS4014:Await.Warning")]
static async Task StartWorkAsync()
{
WorkAsync();
// ...
}
Essentially, you’re telling the compiler that you know what you’re doing and that it shouldn’t be concerned about making a mistake.
The second parameter is the most significant portion of this code. The portion that says “CS4014:” is what disables the warning. On the rest, you can write whatever you wish.
Answered by Fábio
Solution #5
It’s simple to turn off the warning by just assigning the Task when calling it:
Task fireAndForget = WorkAsync(); // No warning now
As a result, you would do in your original post:
static async Task StartWorkAsync()
{
// Fire and forget
var fireAndForget = WorkAsync(); // Tell the compiler you know it's a task that's being returned
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
Answered by noelicus
Post is based on https://stackoverflow.com/questions/22629951/suppressing-warning-cs4014-because-this-call-is-not-awaited-execution-of-the