2014-09-11 96 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,他们运行的线程也可以按任意顺序完成。线程顺序告诉你什么。