SignalR server --> client call not working

2019-06-20 05:28发布

I'm currently using SignalR to communicate between a server and multiple separate processes spawned by the server itself. Both Server & Client are coded in C#. I'm using SignalR 2.2.0.0 On the server side, I use OWIN to run the server. I am also using LightInject as an IoC container.

Here is my code:

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);
    }
}

On the client side, I register this way:

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);
    }
}

On the server side I send a close request the following way:

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

I never receive any callback in CloseRequestedCallback. Neither on the Client side nor on the server side I get any errors in the logs.

What did I do wrong here ?

EDIT 09/10/15

After some research and modifications, I found out it was linked with the replacement of the IoC container. When I removed everything linked to LightInject and used SignalR as is, everything worked. I was surprised about this since LightInject documented their integration with SignalR.

After I found this, I realised that the GlobalHost.DependencyResolver was not the same as the one I was supplying to the HubConfiguration. Once I added

GlobalHost.DependencyResolver = config.Resolver;

before

app.MapSignalR("", config);

I am now receiving callbacks within CloseRequestedCallback. Unfortunately, I get the following error as soon as I call a method from the Client to the Server:

Microsoft.AspNet.SignalR.Client.Infrastructure.SlowCallbackException

Possible deadlock detected. A callback registered with "HubProxy.On" or "Connection.Received" has been executing for at least 10 seconds.

I am not sure about the fix I found and what impact it could have on the system. Is it OK to replace the GlobalHost.DependencyResolver with my own without registering all of its default content ?

EDIT 2 09/10/15

According to this, changing the GlobalHost.DependencyResolver is the right thing to do. Still left with no explanation for the SlowCallbackException since I do nothing in all my callbacks (yet).

1条回答
Juvenile、少年°
2楼-- · 2019-06-20 06:04

Issue 1: IoC Container + Dependency Injection

If you want to change the IoC for you HubConfiguration, you also need to change the one from the GlobalHost so that returns the same hub when requesting it ouside of context.

Issue 2: Unexpected SlowCallbackException

This exception was caused by the fact that I was using SignalR within a Console Application. The entry point of the app cannot be an async method so to be able to call my initial configuration asynchronously I did as follow:

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

Unfortunately for me, this causes a lot of issues as described here & more in details here.

By starting my InitAsync as follow:

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

Everything now runs fine and I don't get any deadlocks.

For more details on the issues & answers, you may also refer to the edits in my question.

查看更多
登录 后发表回答