我正在编写一个MVC Core 2.1 SignalR Web应用程序,它具有一些长期运行的任务。有没有首选的模式可以支持这一点?
最初,我将一些静态成员放入集线器,在其中接收到START或STOP消息,但这是短暂的对象,尽管静态成员仍在处理中,但从其启动代码的实例已处置或消失了,尽管假定以后的消息可以触发STOP。
Take-2将使用Singleton,该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(() =>
{
});
}
}