1

List<TaskClass> TaskListParallel ループを使用して繰り返し処理できる項目があります。

リスト内の項目は、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 に答える