【发布时间】:2026-02-15 14:10:02
【问题描述】:
如何将 SignalR 集线器上下文传递给 ASP .NET Core 2.1 上的 Hangfire 作业?
似乎由于向 Hangfire 传递参数是通过序列化/反序列化完成的,Hangfire 似乎很难重建 SignalR 集线器上下文。
我使用 :
安排作业(在我的控制器中)BackgroundJob.Schedule(() => _hubContext.Clients.All.SendAsync(
"MyMessage",
"MyMessageContent",
System.Threading.CancellationToken.None),
TimeSpan.FromMinutes(2));
然后 2 分钟后,当作业尝试执行时,我有错误:
Newtonsoft.Json.JsonSerializationException:无法创建 Microsoft.AspNetCore.SignalR.IClientProxy 类型的实例。类型是一个 接口或抽象类,不能实例化。
有什么想法吗?
更新 1
我最终使用了 Startup.cs 中定义的静态上下文,并从 Configure() 分配
hbctx = app.ApplicationServices.GetRequiredService<IHubContext<MySignalRHub>>();
所以现在 Hangfire 安排了一个使用静态上下文的集线器助手:
BackgroundJob.Schedule(() => new MyHubHelper().Send(), TimeSpan.FromMinutes(2));
集线器助手通过Startup.hbctx获取上下文
虽然可以,但是有点臭
更新 2
我也尝试使用Access SignalR Hub without Constructor Injection中的方法:
我的后台作业调度变成了:
BackgroundJob.Schedule(() => Startup.GetService().SendOutAlert(2), TimeSpan.FromMinutes(2));
但是这一次,当我到达上面的行时,我有一个异常:
执行请求时发生未处理的异常 System.ObjectDisposedException:无法访问已处置的对象。 对象名称:“IServiceProvider”。
更新 3
谢谢大家。解决方案是创建一个 helper,通过其构造函数通过 DI 获取 hubcontext,然后使用 hangfire 调度 helper 方法 Send 作为后台作业。
public interface IMyHubHelper
{
void SendOutAlert(String userId);
}
public class MyHubHelper : IMyHubHelper
{
private readonly IHubContext<MySignalRHub> _hubContext;
public MyHubHelper(IHubContext<MySignalRHub> hubContext)
{
_hubContext = hubContext;
}
public void SendOutAlert(String userId)
{
_hubContext.Clients.All.SendAsync("ReceiveMessage", userId, "msg");
}
}
然后从任何地方启动后台作业:
BackgroundJob.Schedule<MyHubHelper>( x => x.SendOutAlert(userId), TimeSpan.FromMinutes(2));
【问题讨论】:
-
使用 DI 方法并在需要时解析集线器上下文
-
@Yahia 查看我给here 的以下答案。尽管它主要针对的是重复性工作,但原则仍然是让工作解决必要的依赖关系以执行其功能。
标签: c# asp.net-core signalr hangfire asp.net-core-signalr