Signalr: Konsolenanwendung, die async/await verwendet, stoppt den Empfang nach dem Senden

Erstellt am 22. März 2017  ·  4Kommentare  ·  Quelle: SignalR/SignalR

Ich arbeitete an einem Spike mit zwei Konsolenanwendungen zum Senden und Empfangen von Nachrichten und stieß auf ein seltsames Verhalten. Nachdem in der Abonnentenanwendung eine Methode auf dem Hub mit einem await aufgerufen wurde, erhielt sie keine neuen Nachrichten mehr. Anfänglich bedeutete dies, dass es keine Nachrichten erhielt, da es sofort eine Subscribe Methode aufrief, aber als ich mich eingehender damit beschäftigte, stellte ich fest, dass es ziemlich glücklich empfangen würde, _bis_ es eine Methode aufrief.

Wenn die Methode mit .Wait() statt await aufgerufen wird, ist alles in Ordnung.

Ich bin mir nicht sicher, ob dies mit der Art und Weise zu tun hat, wie Threads in Konsolenanwendungen behandelt werden (im Gegensatz zu WPF-Anwendungen, die ein SynchronizationContext ) oder auf ein Problem im C#-SignalR-Client zurückzuführen ist.

Erwartetes Verhalten

Würde erwarten, await hubProxy.Invoke("Foo"); und weiterhin Nachrichten zu empfangen.

Tatsächliches Verhalten

Die Verwendung von await hubProxy.Invoke("Foo"); unterbricht die Verbindung irgendwie.

Schritte zum Reproduzieren

```c#
Klasse Programm
{
statisch void Main()
{
Run().Wait();
}

statischer asynchroner Task Run()
{
Console.WriteLine("[Subscriber] press Enter to 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();

}
}
```

Bug

Hilfreichster Kommentar

Behoben in e55b89a45618d222e2c37a3b14969923c998899b

Alle 4 Kommentare

Ich sollte darauf hinweisen, dass der Grund, warum ich mir darüber Sorgen mache, obwohl es nur eine Spitze ist, darin besteht, dass der eigentliche Dienst, an dem ich arbeite, von ASP.NET-Web-API-Diensten sowie WPF-Desktopanwendungen verwendet wird.

Es ist ein sehr impliziter Deadlock. Wenn Sie das Tracing einschalten, sehen Sie, dass die Nachrichten noch vom Client empfangen werden, nur Ihr Callback wird nicht aufgerufen, da der vorherige noch nicht abgeschlossen ist:

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({})

Auf Ihrer Seite könnten Sie dies beheben, indem Sie Console.ReadLine(); in await Console.In.ReadLineAsync() ändern, aber ich glaube, dass die Hauptursache hier darin besteht, dass standardmäßig der Benutzercode im selben Thread ausgeführt wird wie die Aufgabe, die mit TaskCompletionSource.SetResult( ). Der Client sollte das Einstellungsergebnis an einen anderen Thread senden oder beim Erstellen des TCS TaskCreationOption.RunContinuationsAsynchronously .

Dieser Thread ist meine async-erwartete Erfahrung in aller Kürze.

Behoben in e55b89a45618d222e2c37a3b14969923c998899b

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen