1

I am developing WebAPI and one of WebApi action methods calls another method that has Async method inside which I don't want to wait for. Just call and forget.

public async Task<IHttpActionResult> Convert(....)
{
//......
//VS warning here
 _asyncJobService.SendWebHook();
//......
}

    public async Task<HttpResponseMessage> SendWebHook()
    {
      //Send and forget, don't wait for result
      return await httpClient.GetAsync("http://stackoverflow.com");
    }

The warning which I get from VS is

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.

What would be the correct way to wire up everything without VS warnings?

Tomas
  • 17,551
  • 43
  • 152
  • 257
  • You can disable the warning explicitly in code. VS should provide a "quick fix" to insert it. – Fildor Nov 12 '19 at 08:56
  • Possible duplicate https://stackoverflow.com/questions/42640730/c-sharp-asynchronous-call-invoke-and-forget – Marmellad Nov 12 '19 at 08:57
  • 2
    You don't need `await` in `SendWebHook` if you don't intend to do something after the call finished. You could reduce the method to `public Task SendWebHook()=>httpClient.GetAsync("http://stackoverflow.com");` – Panagiotis Kanavos Nov 12 '19 at 08:57
  • 2
    As for the warning, assign the task to a variable or `_` without awaiting it. `async` and `await` don't make anything run asynchronously, they help *await* already running operations. If you use `_ =SendWebHook();` the task is discarded and no warning is generated – Panagiotis Kanavos Nov 12 '19 at 08:58
  • Just a note: the [guideline](https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap#naming-parameters-and-return-types) about naming async methods is to append the "Async" suffix to the method's name. – Theodor Zoulias Nov 12 '19 at 09:21
  • @TheodorZoulias Thank you, forgot completely! – Tomas Nov 12 '19 at 10:03

1 Answers1

4

First of all, you don't need async and await in SendWebHook() unless you intend to do something after awaiting for GetAsync. In this case though, you just return.

async and await don't make anything run asynchronously, they help await already running operations.

async is just a keyword that tells the compiler the method is going to use await. In response, the compiler generates a state machine similar to the one used for iterator methods. await in turn, awaits already executing asynchronous operations, it doesn't make anything run asynchronously itself.

In this case, HttpClient.GetAsync is an asynchronous network operation that runs whether or not its result is awaited.

You can reduce that method to :

public Task<HttpResponseMessage> SendWebHook()=>httpClient.GetAsync("http://stackoverflow.com");

As for the warning, you can assign the returned task to a variable or discard it with _ :

_ =SendWebHook();

This tells the compiler that you really don't want to do anything with that task

BUT

Are you sure you want to do that, especially with a GET request? Don't you care what that request returns? Even if it's a health check ping, you probably do care if the monitoring server is down, or times out

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • Maybe I should wrap SendWebHook method to Task.Run() when no await warning and code will be run on the separated thread and will not block execution? – Tomas Nov 12 '19 at 09:03
  • 1
    @Tomas why? `GetAsync` is an async method, even if you call it inside Task.Run it won't *do* anything on that other thread. You'll only waste another thread awaiting for an already asynchronous operation – Panagiotis Kanavos Nov 12 '19 at 09:06
  • Do I correctly understand that if Async method is executed and we do not await it then no main thread will be blocked and will not wait for the async method to finish? As for the second question about implementation, this is a method for WebHook, users enter url to get a notification and this method executed. Due to implementation nature we do not log WebHooks results, so we don't care about Method result too. – Tomas Nov 12 '19 at 09:12
  • 1
    No. I already explained that `async` and `await` are *only* syntactic sugar that allows easy awaiting of already async operations. `GetAsync` is *already* running asynchronously. In any case, Webhooks use POST, not GET, and you probably *do* care about dead webhooks. You don't want to keep calling dead clients after the 100th consecutive failure - *you* are paying for outbound traffic. – Panagiotis Kanavos Nov 12 '19 at 09:15
  • We can also use .ConfigureAwait(false). right? – deathrace Aug 23 '23 at 11:18
  • 1
    @deathrace to do what? This call affects where execution resumes after the async operation, not how it runs or where. This matters in desktop applications, where there's only one UI thread that may be busy when the async operation completes. In Web APIs, where each request is served by a separate thread, there's no such danger. Continuations always run on a new threadpool thread – Panagiotis Kanavos Aug 23 '23 at 11:29