【问题标题】:SignalR connection wouldn't start inside a singleton classSignalR 连接不会在单例类中启动
【发布时间】:2016-06-13 11:39:08
【问题描述】:

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

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

我正在使用这样的单例类:

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

【问题讨论】:

    标签: c# singleton signalr


    【解决方案1】:

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

    StartConnection设为公开并从外部调用它,等待调用:

    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. 您的班级名称在我看来不正确。最好是SignalRClientHelper
    2. 您不需要在构造函数上检查空值,因为毫无疑问它将为空if (hubConnection == null)
    3. 为什么在服务器上有一个“连接”方法?当您执行await hubConnection.Start(); 时,您已经在连接。如果您只想为连接分配用户名,可以在调用 Start() 之前将该用户名传递到标头中:hubConnection.Headers.Add("username", "Mujtaba");
    4. 如果要使此类可靠,则需要处理 SignalR 断开连接(但这将是一个不同的问题)
    5. 每当您调用chatHubProxy.Invoke("whatever"); 时,如果连接在某个时刻丢失,您可能会遇到异常,这将使您的应用程序崩溃。 Wrap it in a try/catch 声明并根据需要处理异常。
    6. StartConnection 应该检查是否已经有连接。因此,如果您调用它 100 次,它只会连接一次。

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

    看看hereherehere

    【讨论】:

    • 酷。我将进行这些更改,看看情况是否更好。关于第 6 点,我如何检查是否已经有连接?
    • 另外,我是否必须在我使用实例的每个片段中调用 StartConnection() 方法?
    • 我已经按照您上面所说的进行了更改,并且它有效 :) 需要一些时间来阅读这些链接,以便更好地理解 SignalR。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    • 2012-03-06
    相关资源
    最近更新 更多