【发布时间】:2020-04-03 23:20:37
【问题描述】:
我对 SignalR 很陌生。我在 React 中设置了一个前端,该前端连接到 SignalR 后端,该后端本身通过 OPC-UA 连接到机器 (这是一个学校项目)
该程序的目的是将实时数据从 PLC 流式传输到我的 React 前端。我现在这样做的方法是:通过前端中的按钮连接 -> 前端调用一个订阅一些 PLC 节点的方法,然后将数据发回。
我的问题是我需要让被调用的方法使用 'while(true)' 循环运行 否则我会收到错误,因为 Hub 对象已被释放。
(这会使 PLC 在节点值更改时调用 SubscriptionHandler,这会导致错误导致 Hub 对象不再存在 我认为)-> (new OpcSubscribeDataChange("ns=6;s=::Program:Cube.Command.CntrlCmd", SubscriptionHandler)
如何在不释放 Hub 对象的情况下以适当的方式保持连接?
这是 SignalR 代码:
using Microsoft.AspNetCore.SignalR;
using System;
using System.Threading.Tasks;
using System.Diagnostics;
using Opc.UaFx.Client;
using Connections;
namespace StreamBackend.Hubs
{
public class DataHub : Hub
{
private IHubContext<DataHub> _context;
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "ConnectedUsers");
await base.OnConnectedAsync();
Console.WriteLine("Client Connected");
OPC.Client.Connect();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR");
await base.OnDisconnectedAsync(exception);
Console.WriteLine("Removed: " + Context.ConnectionId);
}
public DataHub(IHubContext<DataHub> context) {
_context = context;
// Implement check on whether connected already or not
Console.WriteLine("Constructor");
}
public async void SubscriptionHandler(object sender, OpcDataChangeReceivedEventArgs e) {
OpcMonitoredItem item = (OpcMonitoredItem)sender;
var NodeId = Convert.ToString(item.NodeId);
var Value = Convert.ToString(e.Item.Value);
await SendData(NodeId, Value);
}
public async Task SendData(string NodeId, string Value) {
await Clients.All.SendAsync("LatestChange", NodeId, Value);
}
public async Task DataHubConnection()
{
await Clients.All.SendAsync("InvokeMethodFromBackend");
OpcSubscribeDataChange[] nodes = new OpcSubscribeDataChange[] {
new OpcSubscribeDataChange("ns=6;s=::Program:Cube.Command.CntrlCmd", SubscriptionHandler),
new OpcSubscribeDataChange("ns=6;s=::Program:Cube.Command.Parameter[0].Value", SubscriptionHandler)
};
OpcSubscription subscription = OPC.Client.SubscribeNodes(nodes);
// This keeps the "Hub" alive. It is needed, cause it is the SubscriptionHandlers accesspoint
while(true) {
Console.WriteLine("Open");
System.Threading.Thread.Sleep(2000); //Hang out for half a second (testing)
}
}
// 1006 error is when the server closes the connection
}
}
【问题讨论】:
-
我会推荐 Webhooks 而不是信号 R。