0

この例のようなタスクにint変数を渡すと、奇妙な結果になることがよくあります。

List<List<object>> ListToProcess = new List<List<object>>();

// place some lists in list to process
foreach (var temp in Foo)
    ListToProcess.Add(temp);

foreach (var tempArray in ListToProcess)
{
    // initialize each list in ListToProcess                    
}

int numberOfChunks = ListToProcess.Count; 
Task[] tasks = new Task[numberOfChunks];
for (int counter = 0; counter < numberOfChunks; counter++)
{
    tasks[counter] = Task.Factory.StartNew(() =>
        {
            // counter is always = 5  why?   <---------------------------
            var t = ListToProcess[counter];                        
        });
}

どうすればこの問題を解決できますか?

4

4 に答える 4

3

これは閉鎖として知られています。変数の値を使用しているのではなく、変数自体を使用しています。コードが実行されると、Task が定義されたときの値ではなく、実行時の値が使用されます。

この問題を解決するには、次のようなことをすると思います。

for (int counter = 0; counter < numberOfChunks; counter++)
{
    int cur = counter;
    tasks[counter] = Task.Factory.StartNew(() =>
    {
        // counter is always = 5  why?   <---------------------------
        var t = ListToProcess[cur];                        
    });
}
于 2012-04-11T23:01:58.713 に答える
1

StartNew の Action ブロックの「counter」変数がいつアクセスされるかについての保証はありません。発生する可能性があるのは、5 つの値すべてがループされ、タスクが作成され、タスクの実行がスケジュールされることです。

それらが実行されると、以下が実行されます。

var t = ListToProcess[counter];

しかし、この段階でカウントはすでに 5 になっています。

おそらく、並列コレクションを検討する必要がありますか?

ListToProcess.AsParallel().ForAll(list => dosomething(list));

このエリアには他にも多くのオプションがあります。

于 2012-04-11T23:01:18.420 に答える
0
    for (int counter = 0; counter < numberOfChunks; counter++)
    {
        var referenceVariable = new{val=counter};
        tasks[counter] = Task.Factory.StartNew(() =>
            {
                var t = ListToProcess[referenceVariable.val];                        
            });
    }
于 2012-04-11T23:02:13.407 に答える
0

変数がキャプチャされるため、各ループで新しい変数を再宣言することでこれを解決できます。

for (int counter = 0; counter < numberOfChunks; counter++)
{
    int localCounter = counter;
    tasks[localCounter] = Task.Factory.StartNew(() =>
        {
            // counter is always = 5  why?   <---------------------------
            var t = ListToProcess[localCounter];                        
        });
}
于 2012-04-11T23:02:14.810 に答える