我有以下代码:
var x = new Thread(new ThreadStart(Delegate));
x.Start();
这将创建一个新线程并启动它。
我如何检测到线程X已经开始执行,而之后没有do-while循环?
使用信号量、互斥量或Auto/ManualResetEvent。
代码
//Initialize semaphore, set it to BLOCK
ManualResetEvent sema = new ManualResetEvent(false);
void Main()
{
var x = new Thread(Delegate);
//Request the system to start the thread.
//This doesn't mean the CPU will immediately run Delegate method
//but eventually it will do
x.Start(sema);
//Stop here and don't do anything on this thread until the semaphore is FREE
sema.WaitOne();
[continued main thread]
}
void Delegate(Semaphore sema){
//Unblock the semaphore
sema.Set(1);
[your code here]
}
深刻的解释
多线程背后的原则之一是非确定性。如果你没有使用正确的技术,如上所述,你就无法预测在多个线程中完成的操作的行为。如果你有这样的方法
void Main()
{
A();
B();
C();
}
那么你可以确定B在A之前或C之后都不会执行。这同样不适用于多线程。
void Main()
{
new Thread(A).Start();
new Thread(B).Start();
new Thread(C).Start();
D();
}
您确信运行B的线程在运行A的线程之后是started
,但在多线程中,这意味着不同。从MSDN和每一本编程书籍来看,启动线程仅仅意味着请求操作系统在内核中分配适当的设施来支持多线程。如果完成了这一操作(线程已正确创建并计划执行),则该方法返回时不会出错。操作系统可能以任何顺序运行这三个线程,这取决于几个因素。
因此,如果您将它们调试到控制台(假设每个都执行一个Console.WriteLine("Hello, I'm thread A/B/C")
,您可以在不同的执行中获得任何顺序:A,B,C
、A,C,B
、B,C,A
等等
因此,您现在需要确保,但实际上,非常确定,某个特定或每个线程在运行D之前都已经真正启动。事实上,在许多单核CPU的情况下,操作系统应该在每个线程之前运行D
方法。这也是不可预测的!因此,在无法预测A、B和C何时运行之后,你就无法预测D何时运行!!
显式同步是一种强制暂停代码执行并等待事件发生的技术。信号量的发布所描述的事件取决于上下文,因此在您的情况下,您只是告诉主线程"等待Delegate启动,然后做任何您想做的事":)
替代、低效的方法
使用信号量只是使用无限循环进行以下操作的有效方法
volatile bool threadStarted = false;
void Main()
{
var x = new Thread(Delegate);
x.Start();
while (!threadStarted);
[continued main thread]
}
void Delegate(Semaphore sema){
threadStarted = true;
[your code here]
}
使用信号量不会简单地浪费CPU来连续检查某个标志是低还是高
在最基本的级别上,您可以尝试:
if (((Thread)x).ThreadState==ThreadState.Running){
// do something interesting
}
x.ThreadState == System.Threading.ThreadState.Running
您可以使用Thread.ThreadState属性来查找其状态。
假设线程是长寿命的,最简单的方法是检查thread.IsAlive.