Асинхронный обработчик в клиенте сигнализатора .net core - PullRequest
0 голосов
/ 08 июня 2018

Базовый клиент .NET для сигнализатора имеет класс HubConnection, который можно использовать следующим образом.

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

await connection.StartAsync();

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

Я хочу выполнить некоторую асинхронную работу в обработчике событий, но это не такДля меня сразу очевидно, как, так как большинство перегрузок ожидают Action.Использование async void работает, но я не уверен, что это хорошая идея.Кроме того, есть перегрузка с подписью On(string methodName, Type[] parameters, Func<object[], Task>) handler), которая является многообещающей, но я предполагаю, что я ожидал бы перегрузку с On<T>(string methodName, Func<T, Task> handler).Я могу сам создать метод расширения с этой подписью, но когда его там нет, я думаю, что мог пропустить что-то важное?

1 Ответ

0 голосов
/ 07 февраля 2019

Проблема с async void методами заключается в том, что они могут вызвать сбой вашего приложения, если есть необработанное исключение.Прочитайте здесь и здесь .

В этих статьях говорится, что async void разрешено только из-за событий, и это события, которые мы 'мы говорим оНо все равно верно, что исключение может привести к сбою всего вашего приложения.Поэтому, если вы собираетесь туда, убедитесь, что у вас есть блоки try / catch везде, где может быть выброшено исключение (но, тем не менее, исключения могут происходить внутри ваших блоков catch, когда вы пытаетесь его зарегистрировать).

Но async void методы также могут вызывать неожиданное поведение, потому что вызывающий их код не ожидает его завершения, прежде чем уйти и заняться чем-то другим.

Помните, что преимущество await заключается в том, чтоэтот ASP.NET может отключиться, сделать что-то еще и вернуться к остальному коду позже.Обычно это хорошо.Но в данном конкретном случае это может означать, что два (или более) входящих сообщения могут быть обработаны одновременно, и это бросает вызов, для которых те заканчиваются первыми (первое, которое заканчивает обработку, может не быть первым, которое пришло).Хотя в вашем случае это может иметь значение, а может и не иметь значения.

Возможно, вам лучше просто сделать его синхронным и дождаться того, что вы не сможете сделать синхронным:

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

См. здесь и здесь в отношении использования .GetAwaiter().GetResult() вместо .Wait().

...