Signalr: Консольное приложение, использующее async / await, перестает получать после отправки

Созданный на 22 мар. 2017  ·  4Комментарии  ·  Источник: SignalR/SignalR

Я работал над всплеском, используя пару консольных приложений для отправки и получения сообщений, и натолкнулся на немного странное поведение. В приложении-подписчике после того, как оно вызвало метод на концентраторе с использованием await , оно перестало получать новые сообщения. Первоначально это означало, что он никогда не получал сообщения, потому что сразу вызывал метод Subscribe , но, покопавшись в нем, я обнаружил, что он будет получать вполне успешно _, пока_ не вызовет метод.

Когда метод вызывается с .Wait() вместо await все в порядке.

Я не уверен, связано ли это с тем, как потоки обрабатываются в консольных приложениях (в отличие от приложений WPF, у которых есть SynchronizationContext ), или это связано с проблемой в клиенте C # SignalR.

Ожидаемое поведение

Ожидается, что сможет await hubProxy.Invoke("Foo"); и продолжить получать сообщения.

Фактическое поведение

Использование await hubProxy.Invoke("Foo"); каким-то образом разрывает соединение.

Действия по воспроизведению

`` С #
программа класса
{
статическая пустота Main ()
{
Выполнить (). Ждать ();
}

статический асинхронный запуск задачи ()
{
Console.WriteLine ("[Подписчик] нажмите Enter, чтобы войти ...");
Console.ReadLine ();

var hubConnection = new HubConnection("http://localhost:39103/");
var hubProxy = hubConnection.CreateHubProxy("MyHub");
hubProxy.On<string>("OnMessage", msg =>
{
  Console.WriteLine($"Received: {msg}");
});

await hubConnection.Start();

// Receiving messages quite happily at this point

Console.WriteLine("And press Enter again to break the application...");
Console.ReadLine();

await hubProxy.Invoke("Foo", "Bar");

// NO MESSAGES FOR YOU!

Console.WriteLine("And press Enter to Exit, because computers...");
Console.ReadLine();

}
}
`` ''

Самый полезный комментарий

Исправлено в e55b89a45618d222e2c37a3b14969923c998899b

Все 4 Комментарий

Я должен отметить, что причина, по которой я обеспокоен этим, хотя это всего лишь всплеск, заключается в том, что фактическая служба, над которой я работаю, будет потребляться из служб веб-API ASP.NET, а также из настольных приложений WPF.

Это очень неявный тупик. Если вы включите трассировку, вы увидите, что сообщения все еще принимаются клиентом, только ваш обратный вызов не вызывается, потому что предыдущий еще не завершен:

And press Enter to Exit, because computers...
16:44:27.6966075 - b8022975-3d42-4935-952d-7c43a392d049 - WS: OnMessage({"C":"d-59F20992-B,18|S,0|T,1","M":[{"H":"ChatHub","M":"broadcastMessage","A":["adfasf","sadf"]}]})
16:44:28.6936798 - b8022975-3d42-4935-952d-7c43a392d049 - WS: OnMessage({})
16:44:31.4080330 - b8022975-3d42-4935-952d-7c43a392d049 - WS: OnMessage({"C":"d-59F20992-B,19|S,0|T,1","M":[{"H":"ChatHub","M":"broadcastMessage","A":["adfasf","adfsa"]}]})
16:44:36.2056851 - b8022975-3d42-4935-952d-7c43a392d049 - OnError(Microsoft.AspNet.SignalR.Client.Infrastructure.SlowCallbackException: Possible deadlock detected. A callback registered with "HubProxy.On" or "Connection.Received" has been executing for at least 10 seconds.)
16:44:38.6935113 - b8022975-3d42-4935-952d-7c43a392d049 - WS: OnMessage({})

Со своей стороны вы можете исправить это, изменив Console.ReadLine(); на await Console.In.ReadLineAsync() но я считаю, что основная причина здесь в том, что по умолчанию код пользователя выполняется в том же потоке, что и задача, выполненная с помощью TaskCompletionSource.SetResult ( ). Клиент должен отправить результат настройки другому потоку или использовать TaskCreationOption.RunContinuationsAsynchronously при создании TCS.

Вкратце, эта тема - мой опыт работы с async await.

Исправлено в e55b89a45618d222e2c37a3b14969923c998899b

Была ли эта страница полезной?
0 / 5 - 0 рейтинги