Monday, September 3, 2018

SignalR on a background thread in .NET Core

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.


The solution is based on 3 simple steps:
  1. Inject IHubContext into your hub
  2. Span a background thread (or task)
  3. 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.


See Also

About the Author

Bruno Hildenbrand      
Principal Architect, HildenCo Solutions.