C#SignalR异常 - 在收到调用结果之前,连接开始重新连接

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#SignalR异常 - 在收到调用结果之前,连接开始重新连接相关的知识,希望对你有一定的参考价值。

我正在开发2个应用程序,第一个是C#控制台应用程序,另一个是Asp.net Web应用程序。我正在使用SignalR连接两者。

这是我的C#控制台应用程序(客户端)

public class RoboHub
{
    public static IHubProxy _hub;

    public RoboHub()
    {
        StartHubConnection();
        _hub.On("GetGoals", () => GetGoals());
        _hub.On("PrintMessageRobot", x => PrintMessageRobot(x));

        Thread thread = new Thread(MonitorHubStatus);
        thread.Start();
    }

    public void GetGoals()
    {
        //TODO: Does stuff
    }

    public void PrintMessageRobot(string msg)
    {
        Console.WriteLine(msg);
    }

    public void StartHubConnection()
    {
        Console.WriteLine("Robo Hub Starting");
        string url = @"http://localhost:46124/";
        var connection = new HubConnection(url);
        _hub = connection.CreateHubProxy("WebHub");
        connection.Start().Wait();
        Console.WriteLine("Robo Hub Running");
    }

    public void MonitorHubStatus()
    {
        while (true)
        {
            Thread.Sleep(1000);
            _hub.Invoke("Ping", "ping").Wait();
            Console.WriteLine("WebHub Pinged : " + DateTime.Now);
        }
    }
}

控制台应用程序运行时,它会创建RoboHub类的实例。它反过来启动与SignalR集线器的连接,并在一个单独的线程上启动方法MonitorHubStatus,这是我实现的,以检查C#控制台应用程序客户端是否仍然主动连接到集线器。

这是我的Web中心(在Asp.net Web应用程序中)

public class WebHub : Hub
{
    /// <summary>
    /// This method should be called by the Web Clients. 
    /// This method should call the method on the robot clients.
    /// </summary>
    public void GetGoalsHub()
    {
        lock (UserHandler.Connections)
        {
            if (UserHandler.Connections.Any(connection => connection.Contains("Robot")))
            {
                Clients.All.GetGoals();
            }
        }
        //TODO add Error method to call on the client
    }

    /// <summary>
    /// Override Methods
    /// </summary>
    /// <returns></returns>
    public override Task OnConnected()
    {
        lock (UserHandler.Connections)
        {
            //Find out who is connecting based on the User-Agent header
            var query = (from r in Context.Headers
                where r.Key == "User-Agent"
                select r).SingleOrDefault().ToString();

            if (query.Contains("SignalR.Client.NET45"))
            {
                UserHandler.Connections.Add("Robot : " + Context.ConnectionId);
            }
            else
            {
                UserHandler.Connections.Add("Web Application : " + Context.ConnectionId);
                GetGoalsHub();
            }
        }
        Clients.All.UpdateConnections(UserHandler.Connections);
        return base.OnConnected();
    }

    public override Task OnDisconnected(bool stopCalled)
    {
        lock (UserHandler.Connections)
        {
            for (int i = 0; i < UserHandler.Connections.Count; i++)
            {
                if (UserHandler.Connections[i].Contains(Context.ConnectionId))
                {
                    UserHandler.Connections.Remove(UserHandler.Connections[i]);
                }
            }
        }
        Clients.All.UpdateConnections(UserHandler.Connections);
        return base.OnDisconnected(stopCalled);
    }

    public void Ping(string msg)
    {
        Clients.All.PrintMessageRobot("Pong : " + DateTime.Now);
    }
}
public static class UserHandler
{
    public static List<string> Connections = new List<string>(); 
}

目前这两个应用程序似乎工作了一段时间,直到一段时间后这个错误随机出现:连接在收到调用结果之前开始重新连接。

Web集线器还应该调用C#控制台客户端上的任何其他方法,例如GetGoals方法。 '乒乓'方法冻结,一段时间后抛出类似的异常。在此过程中,Web客户端继续完美运行,Web客户端可以与中心服务器来回通信。

任何人都可以建议问题是什么?编辑:进一步的调查让我相信它与线程有关,但是很难找到问题的根源。

答案

我找到了解决方案。

问题在于调用调用:

_hub.Invoke("MethodName", "Parameters").Wait();

在这里我告诉它等待响应但是我没有在Web服务器中编写任何回复机制。

通过切换到:修复此错误:

_hub.Invoke("MethodName", "Parameters");

现在它遵循“即发即忘”的方法,我现在不再得到这个错误。如果其他人得到此错误,请务必检查您是否需要回复。

另一答案

如果发送到服务器端的数据是“不可序列化”(例如)没有[Serializable]属性的业务对象列表,则会收到相同的错误消息

以上是关于C#SignalR异常 - 在收到调用结果之前,连接开始重新连接的主要内容,如果未能解决你的问题,请参考以下文章

SignalR 2.2 客户端未收到任何消息

SignalR

SignalR JavaScript客户端API调用连接

如何在 SignalR 客户端中使用 async/await 和 hub.On

自定义 SignalR 的错误消息

是否有具有“向服务器返回值”功能的 SignalR 替代方案?