Suppressing "warning CS4014: Because this call is not awaited, execution of the current method continues..."
This is not a duplicate of "How to safely call an async method in C# without await".
How do I nicely suppress the following warning?
warning 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.
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);
}
What I tried and did not like:
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
// ...
}
Updated, since the original accepted answer has been edited, I've changed the accepted answer to the one using C# 7.0 discards, as I don't think ContinueWith
is appropriate here. Whenever I need to log exceptions for fire-and-forget operations, I use a more elaborate approach proposed by Stephen Cleary here.
With C# 7 you can now use discards:
_ = WorkAsync();
You can create an extension method that will prevent the warning. The extension method can be empty or you can add exception handling with .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 ASP.NET counts the number of running tasks, so it will not work with the simple Forget()
extension as listed above and instead may fail with the exception:
An asynchronous module or handler completed while an asynchronous operation was still pending.
With .NET 4.5.2 it can be solved by using HostingEnvironment.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));
}