2

2 つの別個のタスクと、それぞれに 2 つの独立した操作があります。t0 はスレッド セーフだと思いますが、t1 についてはわかりません。それが正しいか?並行辞書のパフォーマンスはひどく、コレクションに大量のデータを挿入する必要があります。

var t0 = new Task[2]
{
    Task.Factory.StartNew(()=>
    {
        list1=new sortedlist<int,int>(sortedlist1)
    }
    }),
    Task.Factory.StartNew(()=>
    {
        list2=new sortedlist<int,int>(sortedlist2)
    })
};
Task.WaitAll(t0)

var t1 = new Task[2]
{
    Task.Factory.StartNew(()=>
    {
        foreach (var item in sortedlist1)
        {
            list1.Add(item.Key, item.Value);
        }
    }),
    Task.Factory.StartNew(()=>
    {
        foreach (var item in sortedlist2)
        {
            list2.Add(item.Key, item.Value);
        }
    })
};
Task.WaitAll(t1)
4

2 に答える 2

1

書かれているように、このコードは機能しません。最初のタスクのペアで割り当てられたリストは、2 番目のタスクのペアで使用される変数には割り当てられません。それは無視して、ここでは一般的な概念だけを見てみましょう。

2 つのリストは、別々のスレッドで使用するために別々のスレッドに割り当てる必要はありません。また、各リストを個別のタスクに割り当てる手間を無駄にする必要はまったくありません。リストは、特にメイン スレッドがタスクの完了後にリストを使用する場合に、メイン スレッドによって割り当てることができます。唯一の問題は、1 つのリストが 2 つのスレッドによって同時に変更される可能性があるかどうかです。

list1 が task1 によってのみ読み書きされ、list2 が task2 によってのみ読み書きされる場合、競合することなく、それぞれのタスクでリストに対して必要なことを行うことができます。

両方のタスクが完了するまで待機するために既に行っているように、Task.WaitAll を使用します。両方のタスクが完了すると、メイン スレッドは list1 と list2 を制御して、さらに変更を加えることができます。このような一連の並列実行タスクの後の一般的なフォローアップ操作の 1 つは、複数のタスクの作業を最終出力にマージすることです。(「MapReduce」を参照)

于 2012-11-19T07:16:19.033 に答える
0

これは問題ないようです。タスク間で同じ変数にアクセスしていません。t1[] のタスクは、t0[] のタスクが完了するまで実行されません。

Parallel.Do() を使用して、配列内のタスクを作成し、それらが完了するのを待つ代わりに使用できます。これにより、意図がより明確になり、多くの配列ベースの式が回避されます。

これは実際のコードではなく、例を作成したと思いますか?

于 2012-11-19T07:14:34.723 に答える