首页 文章

如何将SignalR中心上下文传递给ASP .NET Core 2.1上的Hangfire作业?

提问于
浏览
1

如何将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 回答

  • 1

    使用Schedule<T>泛型,您应该能够利用框架的依赖注入功能 .

    BackgroundJob.Schedule<IHubContext<MySignalRHub>>(hubContext => 
        hubContext.Clients.All.SendAsync(
            "MyMessage",
            "MyMessageContent", 
            System.Threading.CancellationToken.None), 
        TimeSpan.FromMinutes(2));
    
  • 1

    Nkosi的回答建议使用 Schedule<T> 泛型指向我使用的最终解决方案:

    首先,我的MySignalRHub只是一个继承自Hub的空类 .

    public class MySignalRHub 
    {
    }
    

    然后,我创建了一个hub helper,它在MySignalRHub上维护一个hubcontext . hubcontext通过ASP.Net Core内置DI机制注入助手类(如here所述) .

    助手类:

    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从代码中的任何位置安排hub helper的方法 SendData() 作为后台作业:

    BackgroundJob.Schedule<MyHubHelper>(h => h.SendData(myData), TimeSpan.FromMinutes(2));
    

相关问题