通过的Parallel.For使用ConcurrentQueue列表中的项目 - 将这项工作?(Pa

2019-10-21 08:55发布

我有一个List<TaskClass> TaskList ,我们可以遍历使用并行循环项目。

在列表中的项目以特定的顺序为TaskClass与自己实现了IComparable排序CompareTo(object obj)方法。 因此,我们需要的项目按顺序采取行动。

请注意,他们没有按顺序完成,刚开始的顺序。

因此任务列表[0]应该启动第一; 然后任务列表[1],任务列表[2],......但是,我们不关心,如果任务列表[2]完成第一或任务列表[0]。

这是简单的代码,我拿出来试图缓解这个:

//Construct a ConcurrentQueue and populate it with our SORTED list
//of TaskClass items so when we go through a parallel loop
//they are acted upon in sorted order. A parallel loop does not
//guarantee ordering, which we need to make sure tasks with a higher
//number are done first.
ConcurrentQueue<TaskClass> cq = new ConcurrentQueue<TaskClass>();
for (int x = 0; x < TaskList.Count; x++)
    cq.Enqueue(TaskList[x]);

Parallel.For(
    0,
    cq.Count,
    new ParallelOptions { MaxDegreeOfParallelism = DISystem.MaxConcurrentThreads },
    x =>
    {
        TaskClass tc = null;
        if (cq.TryDequeue(out tc))
        {
            TaskTypeManager ttm = new TaskTypeManager();
            tc.Working = true;
            tc.Started = DateTime.Now;
            ttm.ProcessTaskItem(tc);
                }
        }
);

现在,我相信这个问题是循环的Parallel.For完成后,原来的List<TaskClass> TaskList将不会被用最新的值更新。

什么是实现这一目标的最佳方式是什么?

随着修改如下代码? (线标有“//新”)

ConcurrentQueue<TaskClass> cq = new ConcurrentQueue<TaskClass>();
for (int x = 0; x < TaskList.Count; x++)
    cq.Enqueue(TaskList[x]);

List<TaskClass> NewTaskList = new List<TaskClass>(); //new
object lockObject = new Object(); //new

Parallel.For(
    0,
    cq.Count,
    new ParallelOptions { MaxDegreeOfParallelism = DISystem.MaxConcurrentThreads },
    x =>
    {
        TaskClass tc = null;
        if (cq.TryDequeue(out tc))
        {
            TaskTypeManager ttm = new TaskTypeManager();
            tc.Working = true;
            tc.Started = DateTime.Now;
            ttm.ProcessTaskItem(tc);
            lock (lockObject) //new
            {
                NewTaskList.Add(tc);
            }
        }
    }
);

NewTaskList.Sort(); //new
TaskList.Clear(); //new
TaskList = NewTaskList.ToList(); //new

或者有没有人有任何其他的想法/建议/改进?

谢谢!

Answer 1:

将这项工作? - 也许大部分的时间,但如果你真的需要它有序。

有一个与声明“他们确实有才能启动”一个内在的问题。 你是什​​么意思与“开始”? 你可能有一个有竞争条件。 考虑这个修改:

x =>
{
    TaskClass tc = null;
    if (cq.TryDequeue(out tc))
    {
        Thread.Sleep(random.Next(0, 1000));
        TaskTypeManager ttm = new TaskTypeManager();
         ...

正如你所看到的,为了发生的唯一的事情就是被出队的项目 - 在那之后,并行踢,没有顺序保证。 你需要某种同步到ProcessTaskItem ,达至您认为任务是实际上是点“开始”。



文章来源: Parallel.For items in a List by using ConcurrentQueue - will this work?