在其执行方法中访问 Task 实例
Access to Task instance inside its execution method
我想创建简单的无限循环,将作业送入基于任务的作业池。
我也想限制当时创建的最大任务数(我知道任务数不必等于线程数)。
我有的是这个:
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 集合中的一些任务完成。但是当我等待主要任务时,它们无法从集合中删除(m_runningTasks),因为 continueTask 尚未完成。
也有人在这个问题中建议 continueWith :
Task does not wait for ContinueWith to finish,但这会创建新任务,我不是在等待它,而是在等待原始任务。
我的问题是如何在任务完成后从其操作(方法)中的集合中删除任务。
示例:
让 MaxDegreeOfParallelism(又名 QueuTaskCount)= 2
所以在第一次迭代中我们将启动任务 A 和 B 两者都带有继续(从列表中删除 A 和 B)让称它们为 A' 和 B'。
所以在第一次迭代中我们有
A->A'
B->B'
在那行 Task.WaitAny() 行我们等待任务
A & B
假设A结束,B继续
所以我们再次迭代,因为 Task.WaitAny 已填满,我们继续下一次迭代
当我们计算时,我们现在应该创建多少任务我们在这一行做
targetCount = QueueTaskCount - m_runningTasks.Count;
正如我们所说
A 结束(又名 runtocomplettiion)
B 运行
但是在集合中(m_running任务)我们仍然可能有也可能没有
A & B 或仅 B - 取决于任务 A'(从集合中删除 A)
这就是问题所在。
在这个迭代中,我不知道集合的状态是什么——但正确的状态只是 B 因为 A 结束了。
有人(不记得是谁,删除了答案提案)建议这不是我应该采用的最佳做法。
您必须从外部解决此问题 - 任务的调用者或创建者负责处理它。
一种解决方案是利用 Task.WhenAny() 并在内部 while 循环中删除已完成的任务(一次一个),但这不是太多可读性也不是很好的代码。
我使用带有 MaxDegreeOfParallelism 的 ActionBlock 解决了这个问题,并在其内部操作中提供了任务 - 如这里所建议的:
Proper way to implement a never ending task. (Timers vs Task)
我想创建简单的无限循环,将作业送入基于任务的作业池。 我也想限制当时创建的最大任务数(我知道任务数不必等于线程数)。
我有的是这个:
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 集合中的一些任务完成。但是当我等待主要任务时,它们无法从集合中删除(m_runningTasks),因为 continueTask 尚未完成。
也有人在这个问题中建议 continueWith : Task does not wait for ContinueWith to finish,但这会创建新任务,我不是在等待它,而是在等待原始任务。
我的问题是如何在任务完成后从其操作(方法)中的集合中删除任务。
示例:
让 MaxDegreeOfParallelism(又名 QueuTaskCount)= 2
所以在第一次迭代中我们将启动任务 A 和 B 两者都带有继续(从列表中删除 A 和 B)让称它们为 A' 和 B'。
所以在第一次迭代中我们有
A->A'
B->B'
在那行 Task.WaitAny() 行我们等待任务
A & B
假设A结束,B继续
所以我们再次迭代,因为 Task.WaitAny 已填满,我们继续下一次迭代
当我们计算时,我们现在应该创建多少任务我们在这一行做 targetCount = QueueTaskCount - m_runningTasks.Count;
正如我们所说 A 结束(又名 runtocomplettiion) B 运行
但是在集合中(m_running任务)我们仍然可能有也可能没有
A & B 或仅 B - 取决于任务 A'(从集合中删除 A)
这就是问题所在。 在这个迭代中,我不知道集合的状态是什么——但正确的状态只是 B 因为 A 结束了。
有人(不记得是谁,删除了答案提案)建议这不是我应该采用的最佳做法。
您必须从外部解决此问题 - 任务的调用者或创建者负责处理它。 一种解决方案是利用 Task.WhenAny() 并在内部 while 循环中删除已完成的任务(一次一个),但这不是太多可读性也不是很好的代码。
我使用带有 MaxDegreeOfParallelism 的 ActionBlock 解决了这个问题,并在其内部操作中提供了任务 - 如这里所建议的: Proper way to implement a never ending task. (Timers vs Task)