如何将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类型的实例 . Type是接口或抽象类,无法实例化 .
任何的想法?
Update 1
我最终使用Startup.cs中定义的静态上下文,并从Configure()分配
hbctx = app.ApplicationServices.GetRequiredService<IHubContext<MySignalRHub>>();
所以现在Hangfire计划使用静态上下文的集线器助手:
BackgroundJob.Schedule(() => new MyHubHelper().Send(), TimeSpan.FromMinutes(2));
并且hub helper获取 Startup.hbctx
的上下文
即使这是有效的,但它有点臭
Update 2
我也尝试使用Access SignalR Hub without Constructor Injection中的方法:
我的后台工作安排成了:
BackgroundJob.Schedule(()=> Startup.GetService() . SendOutAlert(2),TimeSpan.FromMinutes(2));
但是这一次,当我到达上面一行时,我有一个例外:
执行请求时发生未处理的异常System.ObjectDisposedException:无法访问已处置的对象 . 对象名称:'IServiceProvider' .
Update 3
谢谢大家 . 解决方案是创建一个帮助程序,通过其构造函数通过DI获取hubcontext,然后使用hangfire来调度辅助方法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));
2 回答
使用Schedule<T>泛型,您应该能够利用框架的依赖注入功能 .
Nkosi的回答建议使用
Schedule<T>
泛型指向我使用的最终解决方案:首先,我的MySignalRHub只是一个继承自Hub的空类 .
然后,我创建了一个hub helper,它在MySignalRHub上维护一个hubcontext . hubcontext通过ASP.Net Core内置DI机制注入助手类(如here所述) .
助手类:
辅助界面:
最后,我可以使用hangfire从代码中的任何位置安排hub helper的方法
SendData()
作为后台作业: