Owin重启后,SignalR客户端重新连接,但未发布消息

建立:

  1. SignalRServer控制台应用程序:Microsoft.AspNet.SignalR.SelfHost v2.0.3
  2. SignalRClient控制台应用程序:Microsoft.AspNet.SignalR.Client v2.0.3
  3. .NET 4.5.1

我做了以下事情:

  1. 点击进入客户端,在服务器和客户端再次收到消息
  2. 通过点击服务器控制台中的任意键来处理服务器
  3. 通过点击服务器控制台中的任意键重新启动服务器
  4. 客户端重新连接
  5. 点击进入客户端,在服务器上收到消息,但从未再次到达客户端

我希望再次在客户端收到该消息。 我怀疑它与自托管有关,因为我试图在运行IIS的Web应用程序中成功运行客户端。

有任何想法吗?

更新:如果服务器控制台进程被终止并重新启动,则可以重新连接并再次检索消息。

服务器代码

using System; using System.Threading.Tasks; using Microsoft.AspNet.SignalR; using Microsoft.Owin.Hosting; using Owin; namespace SignalRServer { internal class Program { private static void Main(string[] args) { const string url = "http://localhost:8081"; while (true) { using (WebApp.Start(url)) { Console.WriteLine("Server running on {0}. Hit any key to stop.", url); Console.ReadLine(); } Console.WriteLine("Server stopped"); Console.WriteLine("Hit any key to restart, Esc to exit"); ConsoleKeyInfo ki = Console.ReadKey(true); if (ki.Key == ConsoleKey.Escape) return; } } } public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR(); } } public class AuthenticationHub : Hub { public void BroadcastMessageToAll(string message) { Clients.All.sendMessageToClient(message); Console.WriteLine("sendMessageToClient: " + message); } public override Task OnConnected() { Console.WriteLine("OnConnected " + Context.ConnectionId); return base.OnConnected(); } public override Task OnReconnected() { Console.WriteLine("OnReconnected " + Context.ConnectionId); return base.OnReconnected(); } public override Task OnDisconnected() { Console.WriteLine("OnDisconnected " + Context.ConnectionId); return base.OnReconnected(); } } } 

客户代码

 using System; using Microsoft.AspNet.SignalR.Client; namespace SignalRClient { class Program { static void Main(string[] args) { while (true) { var hubConnection = new HubConnection("http://localhost:8081/signalr/hubs"); hubConnection.Closed += () => Console.WriteLine("Closed"); hubConnection.StateChanged += e => Console.WriteLine("StateChanged: " + e.OldState + " " + e.NewState); var hubProxy = hubConnection.CreateHubProxy("AuthenticationHub"); hubProxy.On("sendMessageToClient", info => Console.WriteLine("sendMessageToClient received: " + info)); hubConnection.Start(); Console.WriteLine("Client started - hit Enter to send a message - ESC to stop"); Console.ReadKey(); while (true) { var keyInfo = Console.ReadKey(true); if (keyInfo.Key == ConsoleKey.Escape) break; var message = "Console client : " + DateTime.Now.ToString("HH:mm:ss-fff"); hubProxy.Invoke("BroadcastMessageToAll", message); Console.WriteLine("Client sent BroadcastMessageToAll: " + message); } Console.WriteLine("Client stopping"); hubConnection.Stop(); Console.WriteLine("Client stopped - enter any key start again"); Console.ReadLine(); } } } } 

SignalR团队向我指出了解决方案:默认情况下,SignalR使用GlobalHost,它是一个单独的解析器。 处置后,它永远不会回来。

在为集线器创建配置时,您应该传递一个新的依赖项解析器:

 public class Startup { public void Configuration(IAppBuilder app) { var hubConfiguration = new HubConfiguration {Resolver = new DefaultDependencyResolver()}; app.MapSignalR(hubConfiguration); } } 

Stian的答案很棒。 但是如果需要使用GlobalHost中定义的静态方法,则需要将依赖关系解析器分配给GlobalHost。

以下为我工作:

 public void Configuration(IAppBuilder app) { .... Other configurations .... GlobalHost.DependencyResolver = new DefaultDependencyResolver(); app.MapSignalR(); } 

我用这种方式定义了集线器上下文:

 public sealed class RemoteAdminHub : Hub { #region Properties ///  /// Gets the SignalR Hub context. ///  public static IHubContext HubContext { get { return GlobalHost.ConnectionManager.GetHubContext(); } } #endregion } 

我有几个类似SignalR的问题(在同一场景中不是很明显)。

问题通常是在通信模型request_from_server-> client-> response_to_server中引起的。 当我尝试在接收过程中直接调用客户端代码中的Invoke(发送对服务器的响应)时,我得到了奇怪的行为(无限等待,奇怪的副作用等)。

解决方案是将流程分为两个线程。 一个用于从服务器接收消息到本地ConcurrentQueue。 第二个线程从队列中获取消息,处理它们并将响应发送回服务器(通过Invoke)。 现在SignalR按预期工作。

此问题可能是由于在接收过程完成之前尝试发送响应。 在通常的客户端 – >服务器 – >客户端通信模型中不会发生这种情况。