SignalR 连接不会在单例中启动 class

SignalR connection wouldn't start inside a singleton class

我已经在单例中设置了我的 signalR 连接 class 所以我可以在我的整个项目中使用相同的连接。问题是连接永远不会启动并且代码永远不会在行 await hubConnection.Start() 之外执行,但是当我在单个 class 之外执行此操作时,连接会立即启动。我想知道我做错了什么。 这是我对单例的定义 class:

public sealed class ProxySubscriber
{
    private static volatile ProxySubscriber instance;
    private static object syncRoot = new Object();
    private IHubProxy chatHubProxy = null;
    private HubConnection hubConnection = null;
    public event Action<string, string> OnConnect;
    private ProxySubscriber()
    {
        if (hubConnection == null) { hubConnection = new HubConnection("http://cforbeginners.com:901"); }
        if (chatHubProxy == null) { chatHubProxy = hubConnection.CreateHubProxy("ChatHub"); }

        chatHubProxy.On<string, string>("onConnected", (id, username) => OnConnect.Invoke(id, username));
    }

    private async Task<string> StartConnection()
    {
        await hubConnection.Start();

        return "Connection started..";
    }

    public async void InvokeConnect()
    {
        await chatHubProxy.Invoke("Connect", "Mujtaba");
    }
    public static async Task<ProxySubscriber> GetInstance()
    {
        if (instance == null)
        {
            lock (syncRoot)
            {
                if (instance == null)
                {
                    instance = new ProxySubscriber();

                }
            }
        }

        await instance.StartConnection();
        return instance;
    }
}

我使用单例 class 是这样的:

ProxySubscriber proxySubscriber = ProxySubscriber.GetInstance().Result;
proxySubscriber.OnConnect += proxySubscriber_OnConnect;
proxySubscriber.InvokeConnect();

首先,不要让您的 GetInstance() 异步。仅使用它来创建一个没有更多逻辑的实例。

制作StartConnectionpublic从外面调用,等待调用:

await ProxySubscriber.GetInstance().StartConnection();
ProxySubscriber.GetInstance().OnConnect += proxySubscriber_OnConnect;
ProxySubscriber.GetInstance().InvokeConnect();

如果您需要从非异步方法运行此代码:

Task.Factory.StartNew(async () => {
    await ProxySubscriber.GetInstance().StartConnection();
    ProxySubscriber.GetInstance().OnConnect += proxySubscriber_OnConnect;
    ProxySubscriber.GetInstance().InvokeConnect();
});

更多详情:

  1. 我觉得你的 class 名字不对。最好是 SignalRClientHelper.
  2. 您不需要在构造函数上检查空值,因为毫无疑问它将为空 if (hubConnection == null)
  3. 为什么服务器上有 "Connect" 方法?当您执行 await hubConnection.Start(); 时,您已经连接。如果您只想为连接分配一个用户名,您可以在调用 Start() 之前在 header 中传递该用户名:hubConnection.Headers.Add("username", "Mujtaba");
  4. 如果你想让这个 class 可靠,你需要处理 SignalR 断开连接(但这将是一个不同的问题)
  5. 每当您调用 chatHubProxy.Invoke("whatever"); 时,如果连接在某个时候丢失,您可能会遇到异常,这会使您的应用程序崩溃。 Wrap it in a try/catch 语句并根据需要处理异常。
  6. StartConnection 应该检查是否已经有连接。因此,如果您调用它 100 次,它只会连接一次。

一般来说,你应该学习SignalR connection live cycle,在连接丢失时实现一些逻辑。

看看here, here and here