Как передать контекст-концентратор SignalR в задание Hangfire в ASP .NET Core 2.1?
Кажется, что, поскольку передача аргументов в 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 без внедрения Constructor :
Мое планирование фоновых заданий стало:
BackgroundJob.Schedule (() => Startup.GetService (). SendOutAlert (2),TimeSpan.FromMinutes (2));
Однако на этот раз у меня возникает исключение, когда я достигаю вышеуказанной строки:
Произошло необработанное исключение при выполнении запроса System.ObjectDisposedException: Невозможно получить доступ к удаленному объекту.Имя объекта: 'IServiceProvider'.
Обновление 3
Спасибо всем.Решение состояло в том, чтобы создать помощника, который получает хабконтекст через его конструктор через DI, а затем с помощью Hangfire запланировать вспомогательный метод Отправить как фоновое задание.
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));