设定:
- SignalRServer控制台应用:Microsoft.AspNet.SignalR.SelfHost v2.0.3
- SignalRClient控制台应用:Microsoft.AspNet.SignalR.Client v2.0.3
- .NET 4.5.1
醇>
我执行以下操作:
- 在客户端点击进入,在服务器和客户端再次收到消息
- 通过点击服务器控制台中的任意键来处置服务器
- 通过点击服务器控制台中的任意键重新启动服务器
- 客户端已重新连接
- 在客户端上按Enter键,在服务器上收到消息,但从未再次到达客户端
醇>
我希望再次在客户端收到该消息。我怀疑这与自托管有关,因为我试图在运行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<Startup>(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<string>("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();
}
}
}
}
答案 0 :(得分:6)
SignalR团队向我指出了解决方案: 默认情况下,SignalR使用GlobalHost,它是一个单独的解析器。处置后,它永远不会回来。
在为集线器创建配置时,您应该传递一个新的依赖项解析器:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var hubConfiguration = new HubConfiguration {Resolver = new DefaultDependencyResolver()};
app.MapSignalR(hubConfiguration);
}
}
答案 1 :(得分:1)
Stian的答案很棒。但是如果需要使用GlobalHost中定义的静态方法,则需要将依赖关系解析器分配给GlobalHost。
以下适用于我:
public void Configuration(IAppBuilder app)
{
.... Other configurations ....
GlobalHost.DependencyResolver = new DefaultDependencyResolver();
app.MapSignalR();
}
我用这种方式定义了集线器上下文:
public sealed class RemoteAdminHub : Hub
{
#region Properties
/// <summary>
/// Gets the SignalR Hub context.
/// </summary>
public static IHubContext HubContext
{
get
{
return GlobalHost.ConnectionManager.GetHubContext<RemoteAdminHub>();
}
}
#endregion
}
答案 2 :(得分:0)
我在SignalR中遇到了几个类似的问题(在同一场景中并不是很明显)。
问题通常是在通信模型request_from_server-&gt; client-&gt; response_to_server中引起的。当我尝试在接收过程中直接调用客户端代码中的Invoke(发送对服务器的响应)时,我得到了奇怪的行为(无限等待,奇怪的副作用等)。
解决方案是将流程分为两个线程。一个用于从服务器接收消息到本地ConcurrentQueue。第二个线程从队列中获取消息,处理它们并将响应发送回服务器(通过Invoke)。现在SignalR按预期工作。
这个问题可能是因为尝试在接收程序完成之前发送响应。在通常的客户端 - >服务器 - >客户端通信模型中不会发生这种情况。