Я работал над всплеском, используя пару консольных приложений для отправки и получения сообщений, и натолкнулся на немного странное поведение. В приложении-подписчике после того, как оно вызвало метод на концентраторе с использованием 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();
}
}
`` ''
Я должен отметить, что причина, по которой я обеспокоен этим, хотя это всего лишь всплеск, заключается в том, что фактическая служба, над которой я работаю, будет потребляться из служб веб-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
Самый полезный комментарий
Исправлено в e55b89a45618d222e2c37a3b14969923c998899b