Reputation: 11
While messing around with SignalR I found a behaviour that confuse me.
Calling StartCountDown from a client then make a call to Join behaves like
What I expected.
public class AHub : Hub
{
public async Task Join(string player)
{
await Clients.All.PlayerJoined(player);
}
public async Task StartCountDown()
{
await Task.Delay(10000);
await Clients.All.CountDownStarted();
}
}
This is from a SignalR Hub
Upvotes: 1
Views: 639
Reputation: 81493
This is a common misconception about the async and await pattern. Awaiting something does actually await the completion of the task.
If you want to run the task unobserved (or colloquially known as fire and forget), you could do thus
// task gets started hot and unobserved, remove the warning with a discard
_ = StartCountDownAsync();
Note : An exception that's raised in a method that returns a Task
or Task<TResult>
is stored in the returned task. If you don't await the task or explicitly check for exceptions, the exception is lost. If you await
the task, its exception is rethrown.
As a best practice, you should always await
the call.
Though, you have other options. Which is to start a task, complete other tasks, and then await the completion of the original
Given
public async Task SomeTask1() { }
public async Task SomeTask2() { }
public async Task SlowApiAsync() { }
You might want
var slowApiTask = SlowApiAsync();
await SomeTask1();
await SomeTask2();
await slowApiTask;
Or if you want to run all the tasks concurrently (and yet await them all)
var slowApiTask = SlowApiAsync();
var task1 = SomeTask1();
var task2 = SomeTask2();
await Task.WhenAll(slowApiTask,task1,task2)
Upvotes: 4