如何将SignalR集线器上下文传递到ASP .NET Core 2.1上的Hangfire作业? [英] How can I pass a SignalR hub context to a Hangfire job on ASP .NET Core 2.1?

查看:203
本文介绍了如何将SignalR集线器上下文传递到ASP .NET Core 2.1上的Hangfire作业?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将SignalR集线器上下文传递到ASP .NET Core 2.1上的Hangfire作业?

How can I pass a SignalR hub context to a Hangfire job on ASP .NET Core 2.1?

由于将参数传递给Hangfire是通过序列化/反序列化完成的,因此Hangfire似乎很难重构SignalR集线器上下文.

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.

我使用以下命令安排作业(在我的控制器中):

I schedule the job (in my controller) using :

BackgroundJob.Schedule(() => _hubContext.Clients.All.SendAsync(
        "MyMessage",
        "MyMessageContent", 
        System.Threading.CancellationToken.None), 
    TimeSpan.FromMinutes(2));

然后在2分钟后,当作业尝试执行时,出现错误:

Then after 2 minutes, when the job tries to execute, I have the error :

Newtonsoft.Json.JsonSerializationException:无法创建 Microsoft.AspNetCore.SignalR.IClientProxy类型的实例.类型是 接口或抽象类,无法实例化.

Newtonsoft.Json.JsonSerializationException: Could not create an instance of type Microsoft.AspNetCore.SignalR.IClientProxy. Type is an interface or abstract class and cannot be instantiated.

有什么主意吗?

更新1

我最终使用了Startup.cs中定义的静态上下文,并从Configure()中分配了该静态上下文

I ended up using a static context defined in Startup.cs, and assigned from Configure()

hbctx = app.ApplicationServices.GetRequiredService<IHubContext<MySignalRHub>>(); 

因此,现在Hangfire安排使用静态上下文的集线器帮助程序:

So now Hangfire schedules instead a hub helper that uses the static context :

BackgroundJob.Schedule(() => new MyHubHelper().Send(), TimeSpan.FromMinutes(2)); 

和中心帮助器通过Startup.hbctx

即使可以,但还是有点臭

Even though this is working, it is a little smelly

更新2

我也尝试使用不使用构造函数注入的Access SignalR集线器中的方法:

我的后台作业计划变为:

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:

执行请求时发生未处理的异常 System.ObjectDisposedException:无法访问已处置的对象. 对象名称:"IServiceProvider".

An unhandled exception has occurred while executing the request System.ObjectDisposedException: Cannot access a disposed object. Object name: 'IServiceProvider'.

更新3

谢谢.解决方案是创建一个助手,该助手通过其构造函数通过DI获取hubcontext,然后使用hangfire安排助手方法Send作为后台作业.

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.

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));

推荐答案

Nkosi的答案建议使用Schedule<T>泛型,这使我想到了我使用的最终解决方案:

The answer from Nkosi suggesting to use Schedule<T> generics pointed me to the final solution I used:

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

First, my MySignalRHub is just an empty class inheriting from Hub.

public class MySignalRHub 
{
}

然后,我创建了一个集线器帮助程序,该程序在MySignalRHub上维护一个集线器上下文. Hubcontext通过ASP.Net Core内置的DI机制注入到帮助器类中(如

Then, I created a hub helper which maintains a hubcontext on my MySignalRHub. The hubcontext is injected in the helper class via the ASP.Net Core built-in DI mechanism (as explained 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从代码中的任何地方调度集线器帮助程序的方法SendData()作为后台作业,方法是:

Finally, I can use hangfire to schedule from anywhere in the code the method SendData() of the hub helper as a background job with:

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

这篇关于如何将SignalR集线器上下文传递到ASP .NET Core 2.1上的Hangfire作业?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆