2011-12-01 97 views
2
using System.Collections.Generic; 
using System.Threading; 
using System.Threading.Tasks; 

public sealed class Foo 
{ 
    public int ID; 

    private static readonly Dictionary<int, Foo> Instances = new Dictionary<int, Foo>(); 

    public static void FillInstances() 
    { 
     // here's some magic code to fill .Instances 
    } 

    public static void DoSomething() 
    { 
     var tasks = new Task[Instances.Count]; 
     var i = 0; 
     foreach (var foo in Instances.Values) 
     { 
      var instance = foo; // just to break the reference 
      var task = Task.Factory.StartNew(instance.DoSomethingInternal); 
      tasks[i++] = task; 
      Logger.DebugFormat("translation: task #{0} = id {1}", task.Id, instance.ID); 
     } 
     using (var timer = new Timer(callback => 
     { 
      Logger.DebugFormat("--------------------- {0}", DateTime.Now); 
      foreach (var task in tasks) 
      { 
       var taskInstance = task; // just to break the reference 
       Logger.DebugFormat("task #{0}: {1}", taskInstance.Id, taskInstance.Status); 
      } 
     }, null, TimeSpan.Zero, TimeSpan.FromSeconds(1))) 
     { 
      Task.WaitAll(tasks); 
      Logger.Debug("ready"); 
     } 
    } 

    private void DoSomethingInternal() 
    { 
     Logger.DebugFormat("DoSomethingInternal/task #{0} - id {1}", Task.CurrentId, this.ID); 
    } 
} 

這個問題應該清楚:我打電話給一個靜態方法DoSomething來調用實例方法DoSomethingInternal並行。我的System.Threading.Tasks.Task用法有什麼問題?

爲了我的控制檯的輸出是:

translation: task #1 = id 9 
translation: task #2 = id 5 
translation: task #3 = id 2 
translation: task #4 = id 3 
translation: task #5 = id 7 
translation: task #6 = id 8 
translation: task #7 = id 1 
translation: task #8 = id 10 
DoSomethingInternal/task #8 - id 10 
DoSomethingInternal/task #7 - id 1 
DoSomethingInternal/task #6 - id 8 
DoSomethingInternal/task #5 - id 7 
DoSomethingInternal/task #4 - id 3 
--------------------- 12/01/2011 08:29:57 
task #1: Running 
task #2: Running 
task #3: Running 
task #4: RanToCompletion 
task #5: RanToCompletion 
task #6: RanToCompletion 
task #7: RanToCompletion 
task #8: RanToCompletion 
--------------------- 12/01/2011 08:29:58 
task #1: Running 
task #2: Running 
task #3: Running 
task #4: RanToCompletion 
task #5: RanToCompletion 
task #6: RanToCompletion 
task #7: RanToCompletion 
task #8: RanToCompletion 
--------------------- 12/01/2011 08:29:59 
task #1: Running 
task #2: Running 
task #3: Running 
task #4: RanToCompletion 
task #5: RanToCompletion 
task #6: RanToCompletion 
task #7: RanToCompletion 
task #8: RanToCompletion 

顯然任務#1,#2,#3從來沒有開始,但是這System.Threading.Tasks.Task -instances的.Status告訴我們,這是Running。 那麼這裏有什麼問題?

+0

廣東話確認行爲運行DoSomething,你嘗試過更換Logger.DebugFormat( 「DoSomethingInternal /任務#{0} - ID {1}」,Task.CurrentId,this.ID);更簡單一些。例如的Debug.WriteLine?也許你的記錄器不處理多線程訪問 – Dominik

+0

@Dominik我正在使用log4net ......但我會試一試! –

+0

@Dominik nope,沒有改變任何東西...... :( –

回答

1

我會說你在DoSomethingInternal某處出現了死鎖,你的輸出看起來對我來說線性很差。

當我運行你的代碼,使用Console.WriteLine兩種記錄方式,輸出爲:

translation: task #1 = id 0 
DoSomethingInternal/task #1 - id 0 
translation: task #2 = id 1 
translation: task #3 = id 2 
DoSomethingInternal/task #2 - id 1 
DoSomethingInternal/task #3 - id 2 
DoSomethingInternal/task #4 - id 3 
translation: task #4 = id 3 
translation: task #5 = id 4 
DoSomethingInternal/task #5 - id 4 
DoSomethingInternal/task #6 - id 5 
translation: task #6 = id 5 
translation: task #7 = id 6 
translation: task #8 = id 7 
DoSomethingInternal/task #7 - id 6 
DoSomethingInternal/task #8 - id 7 
translation: task #9 = id 8 
translation: task #10 = id 9 
DoSomethingInternal/task #10 - id 9 
DoSomethingInternal/task #9 - id 8 
ready 

我可以在DoSomething鎖定相同的對象你得到一個相似的輸出和DoSomethingInternal雖然在我的情況它是第一個沒有完成的7個。 ThreadPool線程在我的箱子

+0

主要問題是不是方法沒有完成,他們甚至沒有進入... –

+1

@Andreas據我所知,一些任務將被批處理在線程被阻塞的情況下,這些任務將永遠不會執行 – Amerdrix

+0

感謝您的輸入......但是如果我沒有任何鎖定,該怎麼辦? –