The following fire-and-forget approach is okay for throw-away operations (as opposed to business-critical operations). If we are okay with missing a few messages, an example of a throw-away operation is writing an error to a log.

Run it in DotNetFiddle.

using System;
using System.Threading.Tasks;
					
public class Program
{
	public static void Main()
	{
		var task = WriteToLogAsync();
		Console.WriteLine("The exception goes unnoticed");
		
		Task.Delay(500);
		
		var message = task.Exception.InnerExceptions[0].Message;
		Console.WriteLine(message); // This exception  is lost.
	}
	
	public static async Task WriteToLogAsync()
	{
		System.Console.WriteLine("Trying to write to the log");
		await Task.Yield();
		throw new Exception("This exception is lost");
	}
}

We will not know whether WriteToLogAsync() has completed or has thrown an exception. The lost exception will not cause any problems; it will simply happen outside our awareness. This is fine for truly throw-away operations.

For business critical fire-and-forget operations, a more complex approach is necessary.

Related: