2011-06-17 8 views
2

私は、ASP.NET Webサイトのバックグラウンドタスクシステムの作成を手伝ってくれました。複数のスレッドを1つのタスク用に作成しました。

これはこれはルートTaskから呼び出されTask

Task.Factory.RunNew(RunTimer); 

私のルートです。

private void RunTimer() 
{ 
    while (!cancellationToken.IsCancellationRequested) 
    { 
     var backgroundTasks = _tasks.Values.ToArray(); 
     var tplTasks = new List<Task>(); 
     foreach (var backgroundTask in backgroundTasks) 
     { 
      var newTask = new Task(() => backgroundTask.Run()); 
      tplTasks.Add(newTask); 
      newTask.Start(); 
     } 
     Task.WaitAll(tplTasks.ToArray()); 
     for (int i = 0; i < NumberOfSecondsToWait && 
      !cancellationToken.IsCancellationRequested; i++) 
     { 
      Thread.Sleep(new TimeSpan(0, 0, 1)); 
     } 
    } 
} 

_tasksConcurrentDictionary<string, IBackgroundTask>です。何らかの理由でnewTaskが別のスレッドで2回実行されます。つまり、backgroundTask.Run()が2回呼び出されます。 RunTimerは一度だけ呼び出されます。 NumberOfSecondsToWaitは60です。tplTasksには2つのアイテムしかありません。

誰でもご存知ですか?

+0

問題は何ですか?私には思われるbackgroundTask.Run()は、_tasks内のすべてのタスクに対して呼び出されます。また、睡眠のために使用する必要があります:System.Threading.Thread.Sleep(NumberOfSecondsToWait * 1000) – MrFox

+0

それは2つのスレッドを作成します。一番早い時期にそれをやめようとしています。 –

答えて

4

これは、lambda(特にnewTaskラムダ)が値ではなく変数にバインドするためです。

あなたが必要です:

... 
foreach (var backgroundTask in backgroundTasks) 
{ 
    var localBackgroundTask = backgroundTask; 
    var newTask = new Task(() => localBackgroundTask.Run()); 
    ... 
} 
... 
+1

はい、取り込まれたループ-varの別のバリエーションです。 –

+0

+1もう一つの良い説明はここにあります:http://social.msdn.microsoft.com/Forums/en/parallelextensions/thread/14df8a19-d58e-4303-82ad-ab9c62bdff81 – SwDevMan81

+0

ありがとう。それは素晴らしい仕事をした。 –

関連する問題