SignalR 服务器 --> 客户端调用不起作用

7
我目前正在使用SignalR在服务器和由服务器本身产生的多个独立进程之间进行通信。 服务器和客户端都是用C#编码的。我使用的是SignalR 2.2.0.0版本。 在服务器端,我使用OWIN来运行服务器。 我还使用LightInject作为IoC容器。
这是我的代码:
public class AgentManagementStartup
{
    public void ConfigurationOwin(IAppBuilder app, IAgentManagerDataStore dataStore)
    {
        var serializer = new JsonSerializer
        {
            PreserveReferencesHandling = PreserveReferencesHandling.Objects,
            TypeNameHandling = TypeNameHandling.Auto,
            TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
        };

        var container = new ServiceContainer();
        container.RegisterInstance(dataStore);
        container.RegisterInstance(serializer);
        container.Register<EventHub>();
        container.Register<ManagementHub>();
        var config = container.EnableSignalR();

        app.MapSignalR("", config);
    }
}

在客户端,我这样注册:
public async Task Connect()
{
    try
    {
        m_hubConnection = new HubConnection(m_serverUrl, false);
        m_hubConnection.Closed += OnConnectionClosed;
        m_hubConnection.TraceLevel = TraceLevels.All;
        m_hubConnection.TraceWriter = Console.Out;

        var serializer = m_hubConnection.JsonSerializer;
        serializer.TypeNameHandling = TypeNameHandling.Auto;
        serializer.PreserveReferencesHandling = PreserveReferencesHandling.Objects;

        m_managementHubProxy = m_hubConnection.CreateHubProxy(AgentConstants.ManagementHub.Name);
        m_managementHubProxy.On("closeRequested", CloseRequestedCallback);

        await m_hubConnection.Start();
    }
    catch (Exception e)
    {
        m_logger.Error("Exception encountered in Connect method", e);
    }
}

在服务器端,我通过以下方式发送关闭请求:

var managementHub = GlobalHost.ConnectionManager.GetHubContext<ManagementHub>();
managementHub.Clients.All.closeRequested();

我在CloseRequestedCallback中从未收到过任何回调。无论是客户端还是服务器端,日志中都没有任何错误。

我做错了什么?

编辑 09/10/15

经过一些研究和修改,我发现这与替换 IoC 容器有关。当我移除所有与 LightInject 相关的内容并使用 SignalR 时,一切正常。我对此感到惊讶,因为 LightInject 文档化了它们与 SignalR 的集成

发现这个问题后,我意识到 GlobalHost.DependencyResolver 与我提供给 HubConfiguration 的那个不同。一旦我添加了

GlobalHost.DependencyResolver = config.Resolver;

之前

app.MapSignalR("", config);

我现在正在CloseRequestedCallback中接收回调。不幸的是,当我从客户端调用服务器的方法时,我会立即收到以下错误:

Microsoft.AspNet.SignalR.Client.Infrastructure.SlowCallbackException

可能检测到死锁。已经至少执行了10秒钟的“HubProxy.On”或“Connection.Received”注册的回调。

我不确定我找到的修复程序以及它对系统可能产生的影响。替换GlobalHost.DependencyResolver为自己的是否可以而无需注册其所有默认内容? 编辑2 09/10/15 根据this,更改GlobalHost.DependencyResolver是正确的做法。但仍然没有解释SlowCallbackException,因为我在所有回调中都没有做任何事情(尚未)。

关于您的回调速度慢,也许您需要在后台执行该缓慢的过程,并使用SignalR启动任务?无论如何,这是一个单独的问题。将您的IoC解决方案从问题中移出并制作答案。然后,如果必要,为您的缓慢回调创建一个新问题。 - mason
@mason:我的回调函数(客户端和服务器端)中都没有任何长时间运行的进程。这就是为什么我很惊讶会出现这个错误。我理解你让问题保持在同一个主题下的意见,但这个问题似乎与此有关。 - Joel Bourbonnais
1个回答

3

问题 1: IoC 容器 + 依赖注入

如果您想要更改 HubConfiguration 的 IoC,您还需要更改来自 GlobalHost 的 IoC,以便在上下文之外请求时返回相同的 hub。

问题 2: 意外的 SlowCallbackException

这个异常是由于我在控制台应用程序中使用 SignalR 导致的。应用程序的入口点不能是一个 async 方法,所以为了能够异步调用我的初始配置,我按照以下方式进行:

private static int Main()
{
    var t = InitAsync();
    t.Wait();
    return t.Result;
}

很不幸,对我来说这会导致很多问题,如此处所述here,更详细的内容请参见此处

通过以下方式启动我的InitAsync

private static int Main()
{
    Task.Factory.StartNew(async ()=> await InitAsync());
    m_waitInitCompletedRequest.WaitOne(TimeSpan.FromSeconds(30));
    return (int)EndpointErrorCode.Ended;
}

现在一切运行良好,我不再遇到任何死锁问题。

如需了解更多问题和答案的细节,您还可以参考我的问题编辑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接