2012-11-18 64 views
0

我有一個.NET C#應用程序,我試圖產生多個線程。 該應用程序用於性能測試,並且是一個簡單的控制檯應用程序。 產卵線程工作正常。在.Net/C#中,有沒有辦法等待或在所有工作線程完成處理時收到通知?

我在尋找的是當所有線程完成執行或在我的應用程序中等待所有線程完成時通知的正確機制。 在這一點上,我將打印出結果的摘要。

這裏是我的代碼片段看起來像:

String testName = "foo"; 
String fullTestName; 

// Iterate and create threads 
for (int index = 0; index < numberOfThreads; index++) 
{ 
    fullTestName = String.Format("{0}Thread{1}", testName, index); 

    Thread thread = new Thread(() => PerformanceTest(fullTestName, index, numberOfRows, testToRun)); 

    thread.IsBackground = true; 
    thread.Name = fullTestName; 
    thread.Start(); 
} 

void PerformanceTest(String testName, int iterationNumber, long numberOfRows) 
{ 
    // Insert a bunch of rows into DB 
} 

我看了使用RegisterWaitForSingleObject(),但無法弄清楚如何與我的場景中使用它。

+0

可能的解決辦法:http://stackoverflow.com/questions/358721/be-notified-when-all-background-threadpool-threads-are-finished – Valentin

回答

1

我在尋找的是當所有線程完成執行或在我的應用程序中等待所有線程完成時通知的正確機制。

最簡單的方法就是跟蹤線程(使用數組),然後調用Thread.Join每個線程上依次爲:

Thread[] threads = new Thread[numberOfThreads]; 
for (int index = 0; index < numberOfThreads; index++) 
{ 
    string fullTestName = String.Format("{0}Thread{1}", testName, index); 

    Thread thread = new Thread 
     (() => PerformanceTest(fullTestName, index, numberOfRows, testToRun));  
    thread.IsBackground = true; 
    thread.Name = fullTestName; 
    thread.Start(); 
    threads[index] = thread; 
} 

// Wait for everything to finish 
foreach (Thread thread in threads) 
{ 
    thread.Join(); 
} 

使用任務並行庫將是另一種選擇,但那麼你可能不會有很多線程在同一時間運行 - 它可能會以更好的方式運行,但如果你想要測量特定數量的線程會發生什麼,你需要真正開始它們。

-1

另一個建議是提升PLinq或新異步關鍵字的抽象級別。

這是一個PLinq示例,它將開發人員從線程中抽象出來,並將其從框架中抽象出來。

string testName = "foo"; 
string fullTestName; 

var testIterations = 100; 
Enumerable.Range(0, testIterations).AsParallel().ForAll(i=> 
{ 
    PerformanceTest(testName,i,numberOfRows); 
}); 


void PerformanceTest(String testName, int iterationNumber, long numberOfRows) 
{ 
    // Insert a bunch of rows into DB 
} 
+0

這取決於OP的目標是什麼 - 如果它要看看並行化的程度是多麼的有用,那麼這個將線程抽象化的事實可能是積極無用的。 (不是我downvote,介意你...) –

+0

@JonSkeet我明白,只是想提供一個OP的建議。 – asawyer

2

可以使用Task代替Thread。它爲並行操作提供了更高的抽象級別,並且提供了一個很好的同步方法庫。例如,您可以使用以下內容來等待所有任務完成。

IEnumerable<Task> BeginParallelTests(string fullTestName, int numberOfThreads) 
{ 
    for(var index = 0; index < numberOfThreads; index++) 
    { 
     yield return Task.Factory.StartNew(
      () => PerformanceTest(fullTestName, index, numberOfRows)); 
    } 
} 

然後在你的主要方法,你可以只使用:

Task.WaitAll(BeginParallelTests(testName, numberOfThreads)); 

(也許你將不得不使用類似ToArray()迫使該BeginParallelTest方法的枚舉)

+0

根據我對asawyer的評論:雖然我通常會建議使用更高級別的抽象,但如果OP *想要*仔細控制併發執行的實際線程的數量,TPL並不適合,正因爲它隱藏了很多這個的。 –

+0

考慮到正在運行的任務的性質,您應該在執行選項中包含「LongRunning」。 – casperOne

2

嘗試使用任務而不是線程。

class Program 
{ 

    static Random random = new Random(); 

    static void Main(string[] args) 
    { 
     TaskFactory taskfactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None); 
     var tasks = new List<Task>(); 
     for (int i = 0; i < 10; i++) 
     { 
      var task = taskfactory.StartNew(() => { DoWork("Thread " + i); }); 
      Console.WriteLine(string.Format("Started thread {0}", i)); 
      tasks.Add(task); 
     } 
     Task.WaitAll(tasks.ToArray()); 
    } 

    static void DoWork(string threadname) 
    { 
     int sleeptime = random.Next(10) * 1000; 
     Console.WriteLine(string.Format("Thread {0} sleeping {1}ms", threadname, sleeptime)); 
     Thread.Sleep(sleeptime); 
    } 
} 
相關問題