How to send a message to the client from background task using SignalR? Let's take a look.
SignalR simplifies adding real-time web functionality to apps enabling
server-side code to push content to clients instantly. Good use cases for
SignalR are gaming, maps, dashboards, collaborative and apps that
require notifications.Recently I've been working on a proof of concep project utilizing SignalR.Core and .Net Core and needed to send a message from my Hub to the client from a background job. On this post, let's review how we can send a message to the client from the hub on a background thread.
Solution
The solution is based on 3 simple steps:- Inject IHubContext into your hub
- Span a background thread (or task)
- Send messages back to the clients using IHubContext
Let's take a look.
Step 1 - Inject IHubContext into your hub
private readonly IHubContext<ChatHub> _hubContext;
public ChatHub(UserManager<MgmPlatUser> userManager, ApplicationDbContext context, IHubContext<ChatHub> hubContext)
{
this.userManager = userManager;
this.context = context;
this._hubContext = hubContext; // through this instance we access SignalR in a background tab
}
Step 2 - Span a background thread (or task)
private void DoSomething(string id)
{
// do a bunch of stuff
// ....
// then, span a thread to rerun my command in the background
new Thread(() => OnWaitEnded(m.Id)).Start();
}
Step 3 - Send messages back to the clients using IHubContext
private void
OnWaitEnded(string id){
// wait X secs until my wait period ends if it makes sense....
while (m.ExpiresAt > DateTime.UtcNow){
var ttl = m.ExpiresAt.Subtract(DateTime.UtcNow).Milliseconds;
Thread.Sleep( ttl );
}
_hubContext.Clients.All.SendAsync("OnWaitEnded"
, id, "our event waited");
// call clients using our IHubContext
}
Final Thoughts
This is a simple post to demo how to send messages from a SignalR background job to your client using IHubContext. Note that this should not be your main use case. Usually these background jobs should be processed asynchronously via a backend/webjob/background service decoupled from your front-end. In my case, the need happened during a proof of concept where I didn't need to build a backend to process these longer operations. Since every case is different, I recommend you thinking if this is the best solution for your problem.Hope it helps.
References
- IHubContext - Microsoft Docs
- Calling Clients.All.SendAsync from a secondary thread always throws ObjectDisposedException
- SignalR HubContext | Microsoft Docs
- C# - IIS Background thread and SignalR - Stack Overflow
See Also
- My journey to 1 million articles read
- Why use .NET Core
- Package Management in .NET Core
- Configuration in .NET Core console applications
- Importing CSVs with .NET Core and C#
- Exporting a CSV generated in-memory in ASP.NET with C#
- Building and Running ASP.NET Core apps on Linux
- A simple chat room in Vue.Js