Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices to Fire and Forget an async method to send non essential metric [closed]

Waiting for a non-essential metrics to be sent makes no sense to me, as it adds latency (waiting for the server's response) on each call to the back-end dotnet core service, which might happen multiple times per client call. Still, logging an error on failure is important (I do not need to throw it though, as the metric's failure should not impact the service).

I found multiple ways of doing so. Here is the method to be called in a FireAndForget manner:

public async Task FireAndForget()
{
    try{ await sendTheMetric(); } // Try catch on the await, to log exceptions
    catch(Exception e){ logger.debug(e) }
}

Method 1: Remove the await.

FireAndForget(); // No await in front of the call

Method 2: Seems similar to method 1 to me, as we do not await the Task.Factory.StartNew call.

Task.Factory.StartNew(async () => await MyAsyncTask());

Method 3: Enqueue on the ThreadPool as a workItem.

ThreadPool.QueueUserWorkItem(async o => await FireAndForget());

I have a hard time finding which one I should use for a Fire and forget call to send a non-essential metric. My goal is to not add latency to each calls to my service each time a metric is sent. Logging an error when the metrics fails to be sent is important, but it should never re-throw. The thread context is not important for the execution of the task. The task should always, or at least almost always, be completed.

Which one is the best practice for for requirements? Or are they all the same?

Note: I did not include async void, as it seems risky (if an exception occurs, it might crash, as no Task will wrap it).

like image 359
David Gourde Avatar asked May 15 '20 13:05

David Gourde


People also ask

Is asynchronous fire and forget?

Fire-and-Forget is most effective with asynchronous communication channels, which do not require the Originator to wait until the message is delivered to the Recipient. Instead, the Originator can pursue other tasks as soon as the messaging system has accepted the message.

What happens if you don't await async method?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.


1 Answers

Hope this doesn't muddy the water but there is a 4th option that (from what i have read) is becoming a more accepted option.

Starting with C#7.0 you have the option of using a discard for this sort of instance.

_ = FireAndForget();

This essentially indicates that the task is not needed and thus no return value is expected. Seems to be recommended over Method 1 as it means you are explicitly indicating that it is "fire and forget" (which is less ambiguous and does not look like a coding mistake).

like image 181
Paul Marshall Avatar answered Oct 08 '22 00:10

Paul Marshall