SignalR集线器挂起在IIS上

时间:2015-06-23 07:08:30

标签: asp.net signalr

我们在ASP.NET Web应用程序中使用SignalR库。代码如下所示:

服务器:

[HubName("ticketsCounterHub")]
public class MassivePrintHub : Hub
{
    public void PostTicketsCount(long count)
    {
        Clients.All.Send(count);
    }
}

public class HubFactory
{
    private HubFactory() {}

    public static readonly HubFactory Current = new HubFactory();

    public IHubProxy GetMassivePrintHubProxy()
    {
        var hubConnection = new HubConnection(ConfigUtils.GetRequiredSettingValue("adminPath"));
        var hubProxy = hubConnection.CreateHubProxy("ticketsCounterHub");
        hubConnection.Start().Wait();
        return hubProxy;
    }
}

客户端(JavaScript):

MassivePrintApp.controller("ListController", function ($scope, Dates) {
    var hubManager = (function () {
        var massivePrintHub = $.connection.ticketsCounterHub;
        $.connection.hub.start();
        return { massivePrintHub: massivePrintHub };
    } ());

    hubManager.massivePrintHub.client.Send = function (ticketsCount) {
        $scope.action.Quantity = ticketsCount;
        $scope.$digest();
    };
});

代码的关键部分在MVC控制器中:

public FileResult PrintAction(int actionId, int count, DateTime actionDate, bool isThermo=false)
{
    var ticketsCount = _ticketService.GetTicketsInStatusCount(actionId, actionDate, TicketStatusEnum.ToPrint);

    HubFactory.Current.GetMassivePrintHubProxy().Invoke("PostTicketsCount", ticketsCount);

    var stream = new MemoryStream();
    xmlResponse.Save(stream);
    stream.Flush();
    stream.Position = 0;
    return File(stream,ContentTypeEnum.XML.ToString(),String.Format("массовая {0} мероприятия {1} {2}шт.xml", isThermo?"термопечать":"печать", action.Artist,count));
}

如您所见,我们有这一行:

HubFactory.Current.GetMassivePrintHubProxy().Invoke("PostTicketsCount", ticketsCount);

这导致了这个问题,即每当我们调用它时,就会在IIS上的“请求”部分添加一个集线器实例。

我知道我们已经在JavaScript代码中启动了中心,但我不确定如何使用现有连接或如何摆脱HubFactory或删除已创建的中心实例。

我不明白为什么集线器挂在IIS上。

2 个答案:

答案 0 :(得分:1)

从一个更简单的例子开始,我猜对你有很多帮助。之后,您可以选择以不同方式托管SignalR服务器(控制台应用程序或Windows服务)基础知识不会发生变化

(首次安装SignalR:NuGet:install-package Microsoft.AspNet.SignalR

我制作了一个简单的网络应用示例。该项目有一个Hub类:

using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SRTest
{
    public class MassivePrintHub : Hub
    {
        private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MassivePrintHub>();

        // Can be called from your Javascript code
        public void PostTicketsCount(long count)
        {
            Clients.All.Send(count);
        }

        // Can be called from your c# code
        public static void Static_PostTicketsCount(long count)
        {
            hubContext.Clients.All.Send(count);
        }
    }
}

Owin创业班:

using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(SRTest.Startup))]
namespace SRTest
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var hubConfiguration = new HubConfiguration();
            hubConfiguration.EnableDetailedErrors = true;
            app.MapSignalR(hubConfiguration);
        }
    }
}

Page(Razor只是为了能够调用一个调用c#类的模拟器来发送来自后端的消息):

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>TEST PAGE</title>

    <!--Reference the jQuery library. -->
    <script src='Scripts/jquery-1.6.4.js'></script>
    <!--Reference the SignalR library. -->
    <script src='Scripts/jquery.signalR-2.2.0.js'></script>
    <!--Reference the autogenerated SignalR hub script. -->
    <script src="signalr/hubs"></script>

</head>
<body>

    THIS IS A TEST PAGE
    <!-- Call simulator (trigger event every 5 seconds) -->
    @{SRTest.SendFromBackEnd.SimulateSend();}

<script>
    $(function () {
        var printHub = $.connection.massivePrintHub;

        // when send event happens
        printHub.client.send = function (count) {
            console.log("Send " + count + " tickets");
        };

        $.connection.hub.start().done(function () {
            console.log("Connected");
        });

        $.connection.hub.logging = true;
    });
</script>

</body>
</html>

我添加了一个虚拟类,每隔5秒通过hubcontext触发事件。

using System.Threading;
using System.Web;

namespace SRTest
{
    public class SendFromBackEnd
    {
        public static void SimulateSend()
        {
            new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;
                while (true)
                {
                    MassivePrintHub.Static_PostTicketsCount(2);
                    Thread.Sleep(5000);
                }
            }).Start();

        }
    }
}

我在SignalR中添加了一些记录,添加了一些调试点,它将帮助您理解基础知识,然后构建您计划构建的内容会更容易。

修改

关于挂起请求:只要您的客户端使用SSE或AJAX长轮询连接到SignalR服务器,您就会有一个永不完成的持续请求。 (在AJAX Long-polling的情况下,它会在很短的时间内完成并返回)。在我只使用Javascript客户端的应用程序中,我只看到一个页面打开的请求,我正在收听事件。如果没有打开页面或静态页面则没有请求。 在我使用.NET客户端的应用程序中,只要两个应用程序正在运行,并且两个Sartup类都已执行,即使没有打开页面,请求也将始终存在。 (因为.NET客户端仍在监听事件。)

了解更多信息:http://hanselminutes.com/291/damian-edwards-explains-the-realtime-web-for-aspnet-with-signalr

答案 1 :(得分:0)

这是与线程相关的问题。试试这个

Thread.currentThread().setPriority(priority);