执行长时间运行的作业的任务的 SignalR 池
本文关键字:任务 SignalR 作业 执行 长时间 运行 执行长 | 更新日期: 2023-09-27 18:32:34
我在应用程序中有一个 SignalR 中心 ASP.Net 可以启动不同的任务
public async Task StartHeatingTask()
{
await TaskPool.Instance.TryRun<Heating>(identifier, Heating_ReportProgress);
}
...
void Heating_ReportProgress(TaskProgressStatus status, OperationProgressEventArgs[] args)
{
this.Clients.All.reportProgress(status, args);
}
我的问题是如何避免重复执行同一任务(标识符相同)。这是我当前的TaskPool
实现,尽管我不确定我是否正确使用了locks
和await
的组合:
public class TaskPool
{
private Dictionary<string, LongRunningJob> pool;
private object syncRoot = new object();
public static TaskPool Instance = new TaskPool();
public async Task TryRun<T>(string identifier, LongRunningJob.Progress progressHandler, bool captureContext = false)
where T : LongRunningJob, new()
{
Task worker = null;
if (!this.pool.ContainsKey(identifier))
{
lock (this.syncRoot)
{
if (!this.pool.ContainsKey(identifier))
{
LongRunningJob job = new T {Identifier = identifier};
job.ProgressEventHandler += progressHandler;
this.pool.Add(identifier, job);
worker = job.RunAsync().ContinueWith(task => { this.pool.Remove(identifier); });
}
}
if (worker != null)
{
await worker.ConfigureAwait(captureContext);
}
}
}
public bool Terminate(string identifier)
{
if (this.pool.ContainsKey(identifier))
{
lock (this.syncRoot)
{
if (this.pool.ContainsKey(identifier))
{
this.pool[identifier].Terminate();
return true;
}
}
}
return false;
}
}
我还应该await
由以前的用户调用启动的相同任务。我是C# 5 Task
新手,所以我的概念很可能是错误的,应该完全重新设计。
https://dotnetfiddle.net/SAeTtj
那么
BlockingCollection呢?我认为在您的情况下,它提供了您正在寻找的内容:它是一个线程安全的集合,具有
- 生产者-消费者模式的实现。
- 从多个线程并发添加和获取项目。
在任务池类中,您可以替换
private Dictionary<string, LongRunningJob> pool;
跟
BlockingCollection<T>
元素
查看此页面中的示例
还可以将 ConcurrentQueue 类用于线程安全的先进先出 (FIFO) 集合