c# - 如何将 SignalR 集线器上下文传递给 ASP .NET Core 2.1 上的 Hangfire 作业?
问题描述
如何将 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中的方法:
我的后台作业调度变成了:
BackgroundJob.Schedule(() => Startup.GetService().SendOutAlert(2), TimeSpan.FromMinutes(2));
但是这一次,当我到达上述行时,我有一个例外:
执行请求时发生未处理的异常 System.ObjectDisposedException:无法访问已处置的对象。对象名称:“IServiceProvider”。
更新 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));
解决方案
Nkosi 建议使用Schedule<T>
泛型的答案指出了我使用的最终解决方案:
首先,我的 MySignalRHub 只是一个继承自 Hub 的空类。
public class MySignalRHub
{
}
然后,我创建了一个集线器助手,它在我的 MySignalRHub 上维护一个集线器上下文。hubcontext 通过 ASP.Net Core 内置的 DI 机制注入到辅助类中(如此处所述)。
助手类:
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);
}
}
助手界面:
public interface IMyHubHelper
{
void SendData(String data);
}
最后,我可以使用 hangfire 从代码中的任何位置SendData()
将集线器助手的方法安排为后台作业:
BackgroundJob.Schedule<MyHubHelper>(h => h.SendData(myData), TimeSpan.FromMinutes(2));
推荐阅读
- python-3.x - 日期(以月为单位)的差异将变为负数,“某些”日期(例如 Sep-74)被更改为“2074-09-01”?
- flutter - 从子子小部件通知父小部件
- google-apps-script - 如何使用自定义函数在谷歌电子表格列中返回数组?
- reactjs - React + i18next:为什么我的嵌套键不起作用?
- c# - C# Localization = true 原因“属性‘文本’的代码生成失败。”
- javascript - Knex.js 多个 hasTables 似乎创建了推送数组
- python - AWS CDK,为 Route53 中的现有托管区域创建别名记录
- android - 将鼠标悬停在 Android Studio 中的代码完成选项上时如何查看方法文档?
- swift - 在导航控制器中测试 topviewcontroller
- java - 如何使用 Selenium 和 Java 从 html 中提取文本 2?