記事http://docs.hangfire.io/en/latest/background-processing/tracking-progress.htmlに従って、Hangfire バックグラウンド ジョブの進行状況を追跡しようとしています。
残念ながら、記事に記載されている例は機能していません。サンプル Web アプリケーション ( https://github.com/HangfireIO/Hangfire.Highlighter ) をローカルにダウンロードして実行しました。ジョブが完了した後にクライアントがサブスクライブしても問題ありません。この場合、メッセージはハブから直接送信され、クライアントによって受信されました。そうしないと、Hangfire ジョブからメッセージ呼び出しが呼び出され、何も起こりません。例外も結果もありません。この動作の原因は何ですか? 念のため: hangfire ジョブは非同期で動作しませんでした...
サンプルのコード:
Hangfire ジョブ (Highlight メソッドを参照)
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();
}
}
}
ハブ
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;
}
}
}
OWIN Startup クラスを使用して構成された SingnalR。