Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async handler in signalr .net core client

The .NET core client for signalr have a HubConnection class that can be used in the following way.

HubConnection connection = new HubConnectionBuilder()
            .WithUrl("https://localhost:44321/hub")
            .Build();

await connection.StartAsync();

connection.On<SomeEvent>("HubMethodName", (ev) => Console.WriteLine("EventHandler"))

I want to do some asynchronous work in the event handler, but it is not immediately obvious to me how, since most of the overloads expection an Action. Using async void works, but I'm not sure that's a good idea. Also, there is an overload with the signature On(string methodName, Type[] parameters, Func<object[], Task>) handler) which is promising, but I guess I would have expected one with On<T>(string methodName, Func<T, Task> handler). I can make an extension method with that signature myself, but when it is not there to begin with, I'm thinking that I've might have missed something important?

like image 792
Heap Avatar asked Jun 08 '18 09:06

Heap


1 Answers

The problem with async void methods is that they can crash your app if there's an unhandled exception. Read here and here.

Those articles do say that async void is allowed only because of events, and these are events we're talking about. But it's still true that an exception can crash your whole app. So if you are going to it, make sure you have try/catch blocks anywhere an exception could possibly be thrown (but still, exceptions could happen inside your catch blocks when you try to log it).

But async void methods can also cause unexpected behaviour because the code that calls it is not waiting for it to complete before going off and doing something else.

Remember that the benefit of await is that ASP.NET can go off and do something else and come back to the rest of the code later. Usually that's good. But in this specific case, it can mean that two (or more) incoming messages can get processed at the same time and it's a toss up for which ones finishes first (the first that finishes getting processed may not be the first one that came in). Although that may or may not matter in your case.

You might be better off just making it synchronous, and wait for the stuff that you can't make synchronous:

connection.On<SomeEvent>("HubMethodName", HandleHubMethodName);
private void HandleHubMethodName(ev) {
    SomeAwaitableThing().GetAwaiter().GetResult();
}

See here and here for the benefit of using .GetAwaiter().GetResult() rather than .Wait().

like image 157
Gabriel Luci Avatar answered Oct 11 '22 22:10

Gabriel Luci