Jonatan Almén
Jonatan Almén

Reputation: 11

SignalR is not Async?

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

Answers (1)

TheGeneral
TheGeneral

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

Related Questions