访问任务实例执行方法中的任务实例

本文关键字:实例 任务 执行 访问 方法 | 更新日期: 2023-09-27 18:26:43

我想创建一个简单的无限循环,将作业馈送到基于任务的作业池中。此外,我想限制当时创建的最大任务数(我知道任务数不必等于线程数)。

我有这个:

private readonly HashSet<Task> m_runningTasks = new HashSet<Task>();
private const int QueueTaskCount = 10; //our target task count
.... some method here ....
while (m_run){

  IList<Job> jobs = null;
  lock(m_runningTasks){
    //determine missing job count here
    targetCount = QueueTaskCount - m_runningTasks.Count;
    if(targetCount>0)
      jobs = GetSomeWork(targetCount);
  }
  if(jobs != null && jobs.Count > 0){
     //i want to create jobs here in tasks
     foreach(var job in jobs){
       var task = new Task(job.Execute);
       lock(m_runningTasks)
          m_runningTasks.Add(task); //i could add continueTask instead of task here but that does not solve the problem
       var continueTask = task.ContinueWith(x=> {lock(m_runningTasks){
          m_runningTasks.Remove(x);
       }  };)
       task.Run();
     }
    Task[] taskArray;
    lock(m_runningTasks)
        taskArray = m_runningTasks.ToArray()
    Task.WaitAny(taskArray).Wait(); //HERE is the problem
  }

}

我知道当我创建continueWith它是一个新任务,但我需要阻止当前线程(创建和执行任务),直到它在m_running集合中的一些任务完成。但当我等待主要任务时,由于continueTask尚未完成,它们还无法从collecition(m_runningTasks)中删除。

还有人在这个问题里建议继续:任务不等待ContinueWith完成,但这会创建新任务,我不是在等待,而是在等待原始任务。

我的问题是如何在任务完成后从其操作(方法)内的集合中删除任务。

示例:

让MaxDegreeOfParallelism(Aka QueuTaskCount)=2

因此,在第一次迭代中,我们将启动任务AB,这两个任务都带有continuation(将A和B从列表中删除),让我们称它们为A'B'

所以在第一次迭代中,我们有


A->A'

B->B'

在Task.WWaitAny()行中,我们等待任务

A&B


假设A结束,B继续

所以我们再次迭代,因为Task.WetAny已满,我们继续下一次迭代


当我们计算时,我们现在应该创建多少任务,我们在这一行上完成targetCount=队列任务计数-m_runningTasks.Count;

正如我们所说A结束(也称为运行复合体)B运行

但在集合(m_runningTasks)中,我们可能仍然有,也可能没有

A&B或仅B-取决于任务A'(从集合中删除A)

这就是问题所在。在这种情况下,我不知道集合的状态是什么,但正确的状态只有B,因为A结束了。

访问任务实例执行方法中的任务实例

正如有人(不记得是谁,删除了答案建议)所说,这不是我应该去的最佳实践。

你必须从外部解决这个问题——任务的调用者或创建者负责处理它。一种解决方案是使用Task.WhenAny()并在内部while循环中删除已完成的任务(一次一个),但这既不太可读,也不太好编写代码。

我解决了使用具有MaxDegreeOfParallelism的ActionBlock并在其内部操作中提供任务的问题,如下所示:执行永无止境的任务的正确方式。(计时器与任务)