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

For more posts on .NET Core, please click here.

About the Author

Bruno Hildenbrand      
Solutions Architect, Software Engineer and open-source enthusiast.
.NET, Azure, Go, Linux, Vim, Fedora, i3, Development and Architecture.