Send SignalR client message from background thread

I am trying to track the progress of my Hangfire background jobs using the article http://docs.hangfire.io/en/latest/background-processing/tracking-progress.html

Unfortunately, the example given in the article does not work. I downloaded and launched a sample web application ( https://github.com/HangfireIO/Hangfire.Highlighter ) locally. This is normal when a client signs up after completing a job. In this case, the message was sent directly from the hub and received by the client. Otherwise, the call to the message is called from the Hangfire job, and then nothing happens. No exceptions, no results. What can cause this behavior? Just in case: hangfire jobs cannot work asynchronously ...

Code from sample:

Swamp mission (see selection method)

using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using HangFire.Highlighter.Hubs; using HangFire.Highlighter.Models; using Microsoft.AspNet.SignalR; namespace HangFire.Highlighter.Jobs { public class SnippetHighlighter : IDisposable { private readonly IHubContext _hubContext; private readonly HighlighterDbContext _dbContext; public SnippetHighlighter() : this(GlobalHost.ConnectionManager.GetHubContext<SnippetHub>(), new HighlighterDbContext()) { } internal SnippetHighlighter(IHubContext hubContext, HighlighterDbContext dbContext) { if (hubContext == null) throw new ArgumentNullException("hubContext"); if (dbContext == null) throw new ArgumentNullException("dbContext"); _hubContext = hubContext; _dbContext = dbContext; } public void Highlight(int snippetId) { var snippet = _dbContext.CodeSnippets.Find(snippetId); if (snippet == null) return; snippet.HighlightedCode = HighlightSource(snippet.SourceCode); snippet.HighlightedAt = DateTime.UtcNow; _dbContext.SaveChanges(); _hubContext.Clients.Group(SnippetHub.GetGroup(snippet.Id)) .highlight(snippet.HighlightedCode); } public void Dispose() { _dbContext.Dispose(); } private static async Task<string> HighlightSourceAsync(string source) { using (var client = new HttpClient()) { var response = await client.PostAsync( @"http://hilite.me/api", new FormUrlEncodedContent(new Dictionary<string, string> { { "lexer", "c#" }, { "style", "vs" }, { "code", source } })); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } } private static string HighlightSource(string source) { // Microsoft.Net.Http does not provide synchronous API, // so we are using wrapper to perform a sync call. return RunSync(() => HighlightSourceAsync(source)); } private static TResult RunSync<TResult>(Func<Task<TResult>> func) { return Task.Run<Task<TResult>>(func).Unwrap().GetAwaiter().GetResult(); } } } 

hub

 using System.Data.Entity; using System.Linq; using System.Threading.Tasks; using HangFire.Highlighter.Models; using Microsoft.AspNet.SignalR; namespace HangFire.Highlighter.Hubs { public class SnippetHub : Hub { public async Task Subscribe(int snippetId) { await Groups.Add(Context.ConnectionId, GetGroup(snippetId)); // When a user subscribes a snippet that was already // highlighted, we need to send it immediately, because // otherwise she will listen for it infinitely. using (var db = new HighlighterDbContext()) { var snippet = await db.CodeSnippets .Where(x => x.Id == snippetId && x.HighlightedCode != null) .SingleOrDefaultAsync(); if (snippet != null) { Clients.Client(Context.ConnectionId) .highlight(snippet.Id, snippet.HighlightedCode); } } } public static string GetGroup(int snippetId) { return "snippet:" + snippetId; } } } 

SingnalR is configured using the OWIN startup class.

+6
source share

Source: https://habr.com/ru/post/989093/


All Articles