2014-09-11 97 views
3

如果我有3個線程發生火災。是否有可能知道首先完成哪個線程。是否有可能知道哪個線程先完成?

一些示例代碼

Thread thread1 = new Thread(() => MyFunc()); 
    Thread thread2 = new Thread(() => MyFunc()); 
    Thread thread3 = new Thread(() => MyFunc()); 

    thread1.Start(); 
    thread2.Start(); 
    thread3.Start(); 

    while (thread1.IsAlive || thread2.IsAlive || thread3.IsAlive) 
    { 
     //I need condition to which thread dead first. 
    } 
+3

是否可以切換到'Task'而不是'Thread'?任務具有使這種簡單的類(['Task.WhenAny'](http://msdn.microsoft.com/zh-cn/library/system.threading.tasks.task.whenany(v = vs.110).aspx )) – 2014-09-11 13:22:23

+0

Scott,在框架4.0中可以嗎? – Sam 2014-09-11 13:23:57

+6

如果您需要知道哪個線程先完成,請返回到繪圖板。如果兩個線程同時完成會怎麼樣?重要的時候我無法想到一個情況。 [這樣做的目的是什麼?](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – 2014-09-11 13:24:58

回答

0

一個簡單的解決方法是,你寫線程名當它完成列表或東西嗎?

+0

如果兩個線程先完成,該怎麼辦? – 2014-09-11 13:48:12

+1

@BenjaminTrent無論你寫的任何集合必須是線程安全的,那個線程安全操作將有自己的方法來選擇如何打破一個完美的領帶,找出哪個項目是「第一」,哪個項目是「第二」。 (在這種情況下,線程安全可能是一個像'ConcurrentQueue '一樣安全的集合,或者在普通的'List '附近放置一個'lock') – 2014-09-11 13:52:19

+0

@ScottChamberlain完全是我的觀點,詢問者如何知道哪個完成了「第一個」如果他們在同一時間完成?我的評論措辭不佳,應該明確說明爲什麼我認爲這是一個問題。 – 2014-09-11 13:57:20

1

您可以使用Interlocked.CompareExchange設定中獎線:

static Thread winner = null; 

private static void MyFunc() 
{ 
    Thread.Sleep((int)(new Random().NextDouble() * 1000)); 
    Interlocked.CompareExchange(ref winner, Thread.CurrentThread, null); 
} 

public static void Main() 
{ 
    Thread thread1 = new Thread(() => MyFunc()); 
    Thread thread2 = new Thread(() => MyFunc()); 
    Thread thread3 = new Thread(() => MyFunc()); 

    thread1.Name = "thread1"; 
    thread2.Name = "thread2"; 
    thread3.Name = "thread3"; 

    thread1.Start(); 
    thread2.Start(); 
    thread3.Start(); 

    thread1.Join(); 
    thread2.Join(); 
    thread3.Join(); 

    Console.WriteLine("The winner is {0}", winner.Name); 
} 

Live Demo

UPDATE:如果你不希望所有線程完成你檢查之前,存在使用更簡單的方法AutoResetEvent S和WaitHandle.WaitAny()

private static void MyFunc(AutoResetEvent ev) 
{ 
    Thread.Sleep((int)(new Random().NextDouble() * 1000)); 
    ev.Set(); 
} 

public static void Main() 
{ 
    AutoResetEvent[] evs = {new AutoResetEvent(false), new AutoResetEvent(false), new AutoResetEvent(false)}; 
    Thread thread1 = new Thread(() => MyFunc(evs[0])); 
    Thread thread2 = new Thread(() => MyFunc(evs[1])); 
    Thread thread3 = new Thread(() => MyFunc(evs[2])); 

    thread1.Start(); 
    thread2.Start(); 
    thread3.Start(); 

    int winner = WaitHandle.WaitAny(evs); 

    Console.WriteLine("The winner is thread{0}", winner + 1); 
} 

Live Demo

+0

這裏加入的用途是什麼?如果其中一個完成,我不想等剩餘的線程完成。 – Sam 2014-09-12 04:50:47

+0

@Sam你發佈這個問題時應該寫下來。無論如何,看看我的更新。 – 2014-09-12 07:03:56

0

在代碼的最後一條指令完成後,所有線程都可以有任意的延遲。最後一條指令運行後,操作系統還有一些工作要做。這可能需要很長時間。

因此,找出哪個線程先完成是沒有意義的。 This is the XY-Problem.這個問題沒有意義。它的答案不會幫助你完成任何事情。問真正的問題一個新的問題。

您可能想知道首先發生多種副作用中的哪一種。即使他們按順序完成了A, B,他們運行的線程也可以按任意順序完成。線程順序告訴你什麼。