如何从c#SignalR客户端返回值

时间:2017-09-28 13:48:55

标签: c# signalr signalr-hub signalr.client

我有一个管理许多工作进程的集线器。我想构建一个UI,让我连接到此集线器并从任何这些工作进程中检索处理日志。本质上,这将是一个想要从另一个客户端获取字符串的客户端。我已经能够将客户端A的请求发送给客户端B,但我不知道如何在该响应中返回任何内容。

我在集线器中有一个简单的方法

public void GetRunLog(int runid)
{
    JobRunLog log = null;
    JobRunClient client = this.GetClientByRunID(runid);
    if(client != null)
    {
        var rawlog = Clients.Client(client.ConnectionID).GetRunLog();
        log = JsonConvert.DeserializeObject<JobRunLog>(rawlog);
        Clients.Client(Context.ConnectionId).GetRunLog(log);
    }
}

客户端会收到此请求,但我不知道如何让它返回一个值,以便var rawlog实际包含某些内容。目前,这是我能想到的最好的解决方法。

myHubProxy.On("GetRunLog", (uiconnectionid) =>
{
    string connectionid = uiconnectionid;
    myHubProxy.Invoke("ReturnRunLog", run.ID, run.Log, connectionid).ContinueWith(task => {});
});

然后,这将使工作者客户端在单独的请求中发送回记录,并引用已请求日志的客户端,但它实际上并未向初始请求返回respnonse。我无法看到实现这一目标的方法。而不是使用Invoke,我如何直接将对象返回到发起请求的集线器上的方法?

1 个答案:

答案 0 :(得分:1)

不幸的中心doesn't keeps it's state

  

由于Hub类的实例是瞬态的,因此您无法使用它们   保持状态从一个方法调用到下一个。每一次   服务器接收来自客户端的方法调用,一个新的实例   Hub类处理消息。通过多重维持状态   连接和方法调用,使用一些其他方法,如a   数据库,或Hub类上的静态变量,或其他类   这不是来自Hub。

尝试将逻辑移动到单独的类中,并将实例对象存储在与连接ID相关的静态字典中(不要忘记清除它)。 Whenewer呼叫来到Hub,它将它重新分配到适当的实例,
这是简化的样本

public class TestingLogHub : Hub
{
    public static readonly Dictionary<string, TestInstance> Instances =
                       new Dictionary<string, TestInstance>();

    public void SetParameter(string value)
    {
        Instances[Context.ConnectionId].ContinueWith(value);
    }
    ...
}

public class TestInstance : IDisposable
{
    public TestInstance(string basePath, IHubContext host, string connectionId)
    {...
    }
    public void ContinueWith(string value)
    {
        if (_nextAction == null)
        {
            FinishExecution();
        }
        else
        {
            try
            {
                _nextAction(value);
            }
            catch (Exception exception)
            {
                Error(exception.Message);
                FinishExecution();
            }
        }
    }


    public void RequestParameterFor(Action<string> action, string parameter, string defaultValue = null)
    {
        _nextAction = action;
        _host.Clients.Client(_connectionId).requestParameter(parameter, defaultValue??GetRandomText());
    }
}

因此,当Instance启动时,它正在做一些工作,但目前它需要一些输入它执行RequestParameterFor设置下一个要执行到实例状态的函数并等待{{1的下一次调用}}

这是一个通用示例,在您的情况下,您可以发回一个对象并将其提供给实例,并且可以在该请求结束时处置该实例,如果这是唯一需要的调用