3

So I've been working with background processing and event-driven systems, namely Azure WebJobs and ServiceBus. And while there is extensive use of async/await programming, I'm always wondering if it is generally bad practice to await asynchronous operations when not at all needing the results further in the program. More like a fire and forget.

I know that await won't block a thread but why even force the CPU to return to your method after the await if nothing happens or you don't need the method's result. Why wouldn't one just skip the await on your operation, the CPU never needs to return to your method and the thread can be returned to the pool. This situation is a fire-and-forget one.

EDIT: Code examples

async Task WriteEvent(string event)
{
    //some logic
    Event parsedEvent = new Event(event);
    //other logic

    _eventService.WriteEventAsync(parsedEvent); // no await
}

The alternative to the above code block:

async Task WriteEvent(string event)
{
    //some logic
    Event parsedEvent = new Event(event);
    //other logic

    await _eventService.WriteEventAsync(parsedEvent); // await
}
  • 2
    Giving a code short example (ideally taken from a real program, not an invented one) would probably make your question much interesting. I am curious if you have some production code with really no instruction after the await. – Doc Brown Apr 12 '18 at 7:00
  • @DocBrown, I've added a contrived sample which mimics production code. – ethane Apr 12 '18 at 7:36
  • 1
    And the alternative? await _eventService.WriteEventAsync(parsedEvent); as the last line? – Doc Brown Apr 12 '18 at 7:40
  • @DocBrown correct, question updated. – ethane Apr 12 '18 at 7:44
  • 1
    One thing to keep in mind is that some async libraries/frameworks are "lazy". These won't ever trigger the actual process unless you do a "get" or "eval". This might not be true with C# though. – S.D. Apr 12 '18 at 8:45
4

There is nothing wrong with fire-and-forget asynchronous operation. But you need to make sure you can handle possible exceptions, as there is no one to handle them in such situation.

One possible solution is :

async void WriteEventAsyncEx()
{
    try
    {
        await _eventService.WriteEventAsync(parsedEvent);
    }
    catch(Exception ex)
    {
        // handle exception
        // letting it through would result in UnhandledTaskException killing application
    }
}

async Task WriteEvent(string event)
{
    //some logic
    Event parsedEvent = new Event(event);
    //other logic

    WriteEventAsyncEx(); // no await
}
  • 1
    If anything, add a callback to be called on failure. This way you can safely ignore the called task until something has gone wrong. – Neil Apr 12 '18 at 7:57
  • @Neil, could you maybe provide more context? – ethane Apr 12 '18 at 8:03
  • @ethane I meant, launch the task asynchronously but passing a method that gets called in case of failure, in order to remediate the issue of "not being able to handle possible exceptions". – Neil Apr 12 '18 at 8:17
  • @Neil What's the difference then? You basically have a callback that is called every time, why change it to a callback for errors only? – gnasher729 Apr 12 '18 at 8:22
  • @Neil, wouldn't this need the call to be awaited anyway? The other question is then: is there an advantage of a callback over just try...catch? – ethane Apr 12 '18 at 8:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.