【问题标题】:Real-Time Server to Client Using SignalR使用 SignalR 的实时服务器到客户端
【发布时间】:2016-01-07 00:05:39
【问题描述】:

让我解释一下我的应用程序,以便让读者了解我实际在做什么。

我正在将 MVC5 与 signalR 一起用于 Web 应用程序。

该应用程序包含一个客户端到服务器的连接。另一方面,服务器也有一个连接到 PLC(可编程逻辑控制器)的控制器,它是一个带有硬件 IO 的简单硬件控制器。

我正在使用 SignalR 写入 plc,如下所示: 客户端 (JS) -> SignalRHub -> MVC 控制器 -> PLC

我还需要服务器在PLC发生变化时广播如下: PLC -> MVC 控制器 -> SignalRHub -> 客户端。

MVC 控制器有一个事件,当 plc 发生变化时它会被触发。

问题是,当客户端连接正常时,它确实创建了一个 SignalRHub 的实例,但是当它准备好时,集线器被破坏,因此如果 PLC 上发生更改,它会完全丢失并且无法推送到客户端。

客户端代码为:

$(document).ready(function () {

    var chat = $.connection.chatHub;
    console.log(chat);

    chat.client.writeMessage = function (msg) {
        console.log(msg);
    }

    var i = $.connection.hub.start().then(function (event) {
        $('#send').click(function () {
            console.log("clicked");
            chat.server.plcWrite(true);
        });
    });
});

这意味着(据我所知)在文档准备就绪时创建集线器连接,并且当单击按钮#send 时写入 plc,它工作得非常好。

这是集线器代码:

Controllers.PlcController plc = new Controllers.PlcController();
//public void bMessage()
//{
    // Clients.All.writeMessage(x);
// }


public void plcWrite(bool write)
{
    plc.plcWritebool(write);
    plc._broadcast += plc__broadcast;
}

void plc__broadcast(object sender, EventArgs e)
{
    bool s = plc.plcRead();

    Clients.All.broadcast(s);
}

我正在阅读的问题是,当客户端单击按钮时,它总是会创建一个新控制器,并且在准备好时会丢失。

有没有人知道让集线器始终保持不变并始终与我的控制器保持连接?希望解释清楚,如果您需要更多信息,请随时询问!

编辑:我知道我可以从客户端使用轮询频率,但它会产生大量流量,而且每次轮询时我都必须访问 plc,这不是那么灵活。 plc有变化最好更新客户端!

问候

【问题讨论】:

    标签: asp.net signalr real-time


    【解决方案1】:

    首先,您可以通过集线器和 MVC 控制器与核心逻辑进行大量耦合。

    MVC 控制器和 HUB 都有请求生命周期,试图让它们保持数据的时间比使用静态集合等更长的时间不是好的做法。

    如果 PLC 控制器代码长时间运行,则根本不应从控制器或 HUB 调用它,而是在 HUB 或控制器中将其放入队列中。让 ASP.NET 后台工作人员接手这项工作。在那里处理它。然后我会使用某种低占用空间的服务总线或事件聚合器来发布状态。让 SignalR 使用您自己的库来监听这些状态,或者您可以根据需要使用此库(免责声明,我是作者)。

    https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/wiki

    在此处阅读 ASP.NET 后台工作人员 http://blogs.msdn.com/b/webdev/archive/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-long-background-process-in-asp-net.aspx

    您还可以为您的背景资料创建一个 Windows 服务,并使用服务总线向我的库发出信号。比如 Rabbit MQ 等

    【讨论】:

    • 让我看看我是否理解...所以你的库生成一个事件监听器,每次后台工作人员触发事件(例如当我在 plc 上获得更改时)客户端事件是也被解雇了,我可以根据需要更新客户端,对吗?换句话说,我可以只与后台工作人员一起工作,而无需使用 MVC?
    • 是的,您将需要通过集线器或 WebAPI 控制器或 MVC 控制器以某种方式开始您的工作(尽管 WebAPI 已将 MVC 控制器替换为 REST 的东西)。之后,您的后台工作人员将在您的总线上发布状态,我的库会将它们无缝转发给所有或相关的客户端(它有一个内置的约束 API)
    • 谢谢,我会尽量充分利用你的图书馆,并让你知道。唯一的问题是从哪里开始工作,以便我总是在同一个范围内。
    • 它在app.MapEventProxy<EventBase>();RouteTable.Routes.MapEventProxy<EventBase>(); 上给我一个错误,说我缺少一个指令你有关于如何使用你的库的解决方案吗?我的意思是比文档更详细......对不起,但我是这种编程的新手
    • RouteTable.Routes.MapEventProxy();是 SignalR 1.x 代码,您应该使用第一个语法。 app.MapEventProxy();
    【解决方案2】:

    我意识到这是一个老问题,但我面临着一个非常相似的问题(甚至可以与 PLC 交互——在我的情况下实际上是 FPGA)。我已尝试阅读有关 EventAggregatorProxy 库的信息,但我很难弄清楚它适合架构的位置!

    我正在考虑详细的方法here。这涉及反转依赖关系,因此在您的情况下,PlcController 将引用集线器,可能是这样的:-

    public class PlcController
    {
        IHubContext _hubContext;
    
        public PlcController()
        {
            _hubContext = GlobalHost.ConnectionManager.GetHubContext<MyPlcHub>();
        }
    }
    

    读取 PLC 后,您将使用以下语法广播结果:

    _hubContext.Clients.All.broadcast(s);
    

    您最终是否在解决方案中使用了 EventAggregatorProxy 库?

    【讨论】:

      猜你喜欢
      • 2011-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多