Я пишу веб-приложение MVC Core 2.1 SignalR, в котором есть некоторые долгосрочные задачи. Есть ли предпочтительный шаблон для поддержки этого?
Первоначально я поместил некоторые статические элементы в концентратор, где получены сообщения на START или STOP, но это недолговечные объекты, и хотя статические члены все еще обрабатывали, экземпляр, из которого был запущен код, удаляется или исчезает, хотя предполагается, что более поздние сообщения могут вызвать остановку.
Take-2 - использовать Singleton, который содержит метод, который может быть запущен или остановлен по мере необходимости. Поскольку теперь это выполняется за пределами концентратора, мы должны внедрить его в работающий процесс для обновления прогресса.
Я поместил все остальные значения в раздел служб запуска, чтобы в классе не было экземпляров.
Любые мысли приветствуются
public class MySingletonWorker : ScopedProcessor
{
public bool IsRunning { get; private set; } = false;
CancellationTokenSource _cts;
public MySingletonWorker(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
{
}
public void RunTheProcess()
{
if (!this.IsRunning)
{
this.IsRunning = true;
var scope = _serviceScopeFactory.CreateScope();
_cts = scope.ServiceProvider.GetService<CancellationTokenSource>();
var hub = scope.ServiceProvider.GetService<IHubContext<MyHub>>();
Task.Run(async () =>
{
await WorkerMethod(_cts.Token, hub);
this.IsRunning = false;
});
}
}
async Task ReportProgress(IHubContext<MyHub> hub, string msg)
{
if (hub != null)
{
await hub.Clients.All.SendAsync("ReceiveMessage", msg);
}
}
async Task WorkerMethod(CancellationToken token, IHubContext<MyHub> hub)
{
try
{
await ReportProgress(hub, "Starting");
// Assume a loop of some kind iterates the work to do
while (true != false)
{
// work done here
// Cancelled?
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
}
}
catch (OperationCanceledException exoc)
{
await ReportProgress(hub, exoc.Message);
}
catch (System.Exception ex)
{
await ReportProgress(hub, ex.Message);
}
finally
{
await ReportProgress(hub, "Finished");
}
}
public void CancellProcess()
{
if (_cts != null)
{
_cts.Cancel();
}
}
protected override async Task ExecuteAsync(CancellationToken ct)
{
await Task.Run(() =>
{
});
}
}