简体   繁体   English

如何将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?

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.

相关问题 您如何在控制器外部获得对ASP.NET Core SignalR集线器上下文的引用? - How do you get a reference to an ASP.NET Core SignalR hub context outside of a controller? 如何在ASP.NET Core应用程序中将记录器传递到服务器端的SignalR集线器 - How to pass logger into SignalR hub on server side in ASP.NET Core application ASP.NET Core MVC应用程序(带SignalR)的每个用户的周期性HangFire作业 - Recurring HangFire job for each user of an ASP.NET Core MVC app (w/ SignalR) 在两个ASP.NET Core 2.1 Razor Web应用程序中将SignalR既用作集线器又用作客户端 - Use SignalR as both a Hub and a Client in two ASP.NET Core 2.1 Razor web apps .NET Core 2.1 / Angular - SignalR只需2分钟即可连接到集线器 - .NET Core 2.1 / Angular - SignalR takes exactly 2 minutes to connect to hub 在asp.net core 2.1上使用Hangfire发送电子邮件 - Sending emails using Hangfire on asp.net core 2.1 访问 SignalR 集线器上下文。来自 ASP.NET 核心中 singleton 服务的项目 - Access SignalR Hub Context.Items from an singleton service in ASP.NET Core 如何在 ASP.NET 5 (vNext) 中设置 SignalR Hub 依赖注入? - How can I set up SignalR Hub Dependency Injection in ASP.NET 5 (vNext)? 如何将数据上下文传递给 Asp.Net Core 中的 static 方法 - How can pass a data context to a static method in Asp .Net Core asp.net core 3.1 SignalR:将复杂对象从 javascript 客户端传递到集线器 - asp.net core 3.1 SignalR: pass complex object from javascript client to Hub
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM