I have setup my signalR connection inside a singleton class so I can use the same connection throughout my entire project. The problem is that the connection never starts and the code never executes beyond the line await hubConnection.Start()
however when I do this outside the single class, then the connection is initiated in an instant. I wonder what I'm doing wrong.
Here's my definition of the singleton 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;
}
}
I'm using the singleton class like this:
ProxySubscriber proxySubscriber = ProxySubscriber.GetInstance().Result;
proxySubscriber.OnConnect += proxySubscriber_OnConnect;
proxySubscriber.InvokeConnect();
First thing, don´t make your GetInstance() async. Use it just to create an instance with no more logic in it.
Make
StartConnection
public and call it from outside, awaiting the call:If you need to run this code from non async methods:
More details:
SignalRClientHelper
.if (hubConnection == null)
await hubConnection.Start();
you are already connecting. If you just want to asign a username to a connection, you can pass that username in a header before you call Start():hubConnection.Headers.Add("username", "Mujtaba");
chatHubProxy.Invoke("whatever");
you may get an exception if the connection is lost at some point, and that will make your application crash. Wrap it in a try/catch statement and handle the exception as you need.StartConnection
should check if there is already a connection going on. So if you call it 100 times, it would connect just once.In general, you should learn from SignalR connection live cycle and implement some logic at the time the connection is lost.
Take a look here, here and here