[英]How can I pass a SignalR hub context to a Hangfire job on ASP .NET Core 2.1?
How can I pass a SignalR hub context to a Hangfire job on ASP .NET Core 2.1? 如何将SignalR集线器上下文传递到ASP .NET Core 2.1上的Hangfire作业?
It seems that since passing arguments to Hangfire is done via serialization/deserialization, it seems that Hangfire has hard-time reconstructing the SignalR hub context. 似乎由于将参数传递给Hangfire是通过序列化/反序列化完成的,因此Hangfire似乎很难重构SignalR集线器上下文。
I schedule the job (in my controller) using : 我使用以下命令调度作业(在我的控制器中):
BackgroundJob.Schedule(() => _hubContext.Clients.All.SendAsync(
"MyMessage",
"MyMessageContent",
System.Threading.CancellationToken.None),
TimeSpan.FromMinutes(2));
Then after 2 minutes, when the job tries to execute, I have the error : 然后2分钟后,当作业尝试执行时,出现错误:
Newtonsoft.Json.JsonSerializationException: Could not create an instance of type Microsoft.AspNetCore.SignalR.IClientProxy.
Newtonsoft.Json.JsonSerializationException:无法创建类型为Microsoft.AspNetCore.SignalR.IClientProxy的实例。 Type is an interface or abstract class and cannot be instantiated.
类型是接口或抽象类,无法实例化。
Any idea? 任何想法?
Update 1 更新1
I ended up using a static context defined in Startup.cs, and assigned from Configure() 我最终使用了Startup.cs中定义的静态上下文,并从Configure()分配了该上下文
hbctx = app.ApplicationServices.GetRequiredService<IHubContext<MySignalRHub>>();
So now Hangfire schedules instead a hub helper that uses the static context : 因此,现在,Hangfire计划使用静态上下文的中心帮助程序:
BackgroundJob.Schedule(() => new MyHubHelper().Send(), TimeSpan.FromMinutes(2));
and the hub helper gets the context with Startup.hbctx
中心帮助器通过
Startup.hbctx
获取上下文
Even though this is working, it is a little smelly 即使这样做有效,也有点臭
Update 2 更新2
I tried also using the approach in Access SignalR Hub without Constructor Injection : 我还尝试了在没有构造函数注入的情况下在Access SignalR Hub中使用该方法:
My background job scheduling became : 我的后台作业调度为:
BackgroundJob.Schedule(() => Startup.GetService().SendOutAlert(2), TimeSpan.FromMinutes(2)); BackgroundJob.Schedule(()=> Startup.GetService()。SendOutAlert(2),TimeSpan.FromMinutes(2));
However this time, I have an exception when I reach the above line: 但是这次,当我到达上面的行时,我有一个例外:
An unhandled exception has occurred while executing the request System.ObjectDisposedException: Cannot access a disposed object.
执行请求System.ObjectDisposedException时发生未处理的异常:无法访问已处置的对象。 Object name: 'IServiceProvider'.
对象名称:“ IServiceProvider”。
Update 3 更新3
Thanks all. 谢谢大家 The solution was to create a helper that gets the hubcontext via its constructor via DI, and then using hangfire to schedule the helper method Send as the background job.
解决方案是创建一个帮助程序,该帮助程序通过DI的构造函数获取集线器上下文,然后使用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");
}
}
Then launching the background job from anywhere with : 然后使用以下命令从任何地方启动后台作业:
BackgroundJob.Schedule<MyHubHelper>( x => x.SendOutAlert(userId), TimeSpan.FromMinutes(2));
Using Schedule<T>
generics you should be able to take advantage of the dependency injection capabilities of the framework. 使用
Schedule<T>
泛型,您应该能够利用框架的依赖注入功能。
BackgroundJob.Schedule<IHubContext<MySignalRHub>>(hubContext =>
hubContext.Clients.All.SendAsync(
"MyMessage",
"MyMessageContent",
System.Threading.CancellationToken.None),
TimeSpan.FromMinutes(2));
The answer from Nkosi suggesting to use Schedule<T>
generics pointed me to the final solution I used: Nkosi的建议使用
Schedule<T>
泛型的答案将我带到了我使用的最终解决方案:
First, my MySignalRHub is just an empty class inheriting from Hub. 首先,我的MySignalRHub只是一个继承自Hub的空类。
public class MySignalRHub
{
}
Then, I created a hub helper which maintains a hubcontext on my MySignalRHub. 然后,我创建了一个集线器帮助程序,它在MySignalRHub上维护一个集线器上下文。 The hubcontext is injected in the helper class via the ASP.Net Core built-in DI mechanism (as explained here ).
该hubcontext在辅助类通过ASP.Net核心内建DI机构喷射(如解释在这里 )。
The helper class: 助手类:
public class MyHubHelper : IMyHubHelper
{
private readonly IHubContext<MySignalRHub> _hubContext;
public MyHubHelper(IHubContext<MySignalRHub> hubContext)
{
_hubContext = hubContext;
}
public void SendData(String data)
{
_hubContext.Clients.All.SendAsync("ReceiveMessage", data);
}
}
The helper interface: 助手界面:
public interface IMyHubHelper
{
void SendData(String data);
}
Finally, I can use hangfire to schedule from anywhere in the code the method SendData()
of the hub helper as a background job with: 最后,我可以使用hangfire从代码中的任何地方调度集线器帮助程序的
SendData()
方法作为后台作业,它具有:
BackgroundJob.Schedule<MyHubHelper>(h => h.SendData(myData), TimeSpan.FromMinutes(2));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.