SignalR断开连接并且不重新连接

时间:2014-05-18 22:01:01

标签: signalr signalr-hub

每当我的应用程序重置时,signalR断开但不重新连接。

我有一个长时间运行的服务器任务,它在每个任务完成时向客户端发送更新。

// inside action executed on every completion of a task
var h = new ForceHub();
h.MessageSent(email);

上面的代码在应用程序重置时停止发送更新(我可以通过触摸web.config来模拟此问题)。

我想要一种重新连接到客户端的方法。目前,用户必须重新加载页面才能再次获取更新。

这是我的中心定义

public class ForceHub : Hub
{
    public void MessageSent(string text)
    {
        GetContext().Clients.All.sent(text);
    }

    public void UpdateStatus(string msg)
    {
        GetContext().Clients.All.status(msg);
    }

    IHubContext GetContext()
    {
        return GlobalHost.ConnectionManager.GetHubContext<ForceHub>();
    }
    public override Task OnConnected()
    {
        try {
            IoC.Resolve<ILogger>().Info("SignalR Connected -----------");
        }catch (Exception){}

        return base.OnConnected();
    }

    public override Task OnDisconnected()
    {
        try {
            IoC.Resolve<ILogger>().Info("SignalR Disconnected -----------");
        }
        catch (Exception) { }
        return base.OnDisconnected();
    }

    public override Task OnReconnected()
    {
        try {
            IoC.Resolve<ILogger>().Info("SignalR Re-Connected -----------");
        }
        catch (Exception) { }
        return base.OnReconnected();
    }
}

我可以看到启动后触发的已连接重新连接事件,但是在触摸web.config后,我没有看到任何这些事件被触发。

我尝试在客户端上捕获此信息,但此事件并非如此:

$.connection.hub.disconnected(function () {
    console.error('signalR disconnected, retrying connection');
    logError('Signal lost.');
    setTimeout(function () { connection.start(); }, 1000);
});

更新

我还迷上了State Changed事件,它确实被触发了,但下面的重新连接尝试不起作用。

        $.connection.hub.stateChanged(function (state) {
            console.debug('signalR state changed', state);
            if (state.newState == 1) {
                console.debug('restarting');
                setTimeout(function () { $.connection.hub.start(); }, 1000);
            }
        });

此事件被触发两次:newState为2,然后是1.

1 个答案:

答案 0 :(得分:1)

我可能有一个线索......触摸Web.config会产生一个appPool Recycle,这意味着将为新请求创建一个新的工作进程,而现有进程将持续一段时间,直到剩余的请求结束或超时到达了。未终止超时期限的请求将被终止。

Signalr客户端在旧进程中运行长时间运行的任务时重新连接到新进程,因此在执行长时间运行的任务时

GlobalHost.ConnectionManager.GetHubContext<ForceHub>(); 

当客户端连接到“新”集线器时,您实际上获得了“旧”集线器的引用。 这就是为什么Wasp执行的测试工作的原因:他正在新的请求发布在新创建的工作进程中处理的信号器中心。

您可以尝试配置singalr背板(https://www.asp.net/signalr/overview/performance/scaleout-in-signalr),使用Sql Server(https://www.asp.net/signalr/overview/performance/scaleout-with-sql-server)配置它非常容易。背板应该能够连接两个工作进程,希望您能在客户端获得通知。

如果出现此问题,即使没有背板,新请求生成的通知也会有效。请注意,背板的真正目的是扩展信号器,即连接它们之间的Web服务器场。

另外请记住,在IIS中运行长时间运行的任务很难实现,因为IIS会定期执行appPool循环并且对执行请求有超时限制。我建议您阅读以下帖子:http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx “如果你认为自己可以自己写一个后台任务,那么你很可能会错。我并没有贬低你的技能,我只是说它很微妙。另外,你为什么要这么做?“

希望这有帮助