1

我有一个List<TaskClass> TaskList项目,我们可以使用 Parallel 循环对其进行迭代。

列表中的项目按特定顺序排序,因为 TaskClass 使用自己的CompareTo(object obj)方法实现 IComparable。因此,我们需要按顺序执行的项目。

请注意,它们不必按顺序完成,只需按顺序开始即可。

因此 TaskList[0] 应该首先启动;然后是 TaskList[1], TaskList[2], ... 但是,我们不关心 TaskList[2] 是先完成还是 TaskList[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值不会更新为最新值。

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

修改后的代码如下?(标有“//new”的行)

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

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

谢谢!

4

1 回答 1

1

这行得通吗?-不。也许大多数时候,但如果你真的需要订购它就不会。

“他们确实必须按顺序开始”的说法存在一个固有的问题。“开始”是什么意思?你可能在那里有一个竞争条件。考虑这个修改:

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

正如您所看到的,唯一按顺序发生的事情就是您的项目被出列 - 之后,并行性开始起作用,并且不保证任何顺序。您需要某种同步到ProcessTaskItem,直到您认为任务实际“开始”为止。

于 2014-12-05T03:31:57.257 回答