探秘System.Threading系列 第二篇:还是Thread,Thread.Start 和 Thread.Join

本文探讨了使用Thread和ThreadPool启动线程的方法,通过示例代码展示了Thread.Join方法在不同场景下的行为差异,包括线程阻塞及执行顺序的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 开始一个Thread
开始一个Thread很简单,声明一个Thread实例,然后调用Start方法即可

Thread.Start
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->Thread threadA = new Thread(new ThreadStart(WorkMethod));
threadA.Start();

Thread threadB 
= new Thread(new ParameterizedThreadStart(WorkMethodWithParam));
threadB.Start(obj);


2. Thread.Join阻塞调用线程,直到某个线程终止为止。
我按照msdn上的解释的理解是:
threadA.Join()方法是用来阻塞threadA线程,直到在threadA开始执行之后启动的线程执行完毕(或者Sleep了)之后,才开始执行threadA线程的方法

但是事实并非如我所想,下面是msdn上的例子,先声明了一个thread实例,然后将一个方法放入ThreadPool中执行,并调用thread的Join方法以阻塞thread的执行。显示结果在预料之中

MSDN Thread.Join例子
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->using System;
using System.Threading;

class IsThreadPool
{
    
static void Main()
    {
        AutoResetEvent autoEvent 
= new AutoResetEvent(false);

        Thread regularThread 
= 
            
new Thread(new ThreadStart(ThreadMethod));
        regularThread.Start();
        ThreadPool.QueueUserWorkItem(
new WaitCallback(WorkMethod), 
            autoEvent);

        
// Wait for foreground thread to end.
        regularThread.Join();

        
// Wait for background thread to end.
        autoEvent.WaitOne();
    }

    
static void ThreadMethod()
    {
        Console.WriteLine(
"ThreadOne, executing ThreadMethod, " +
            
"is {0}from the thread pool."
            Thread.CurrentThread.IsThreadPoolThread 
? "" : "not ");
    }

    
static void WorkMethod(object stateInfo)
    {
        Console.WriteLine(
"ThreadTwo, executing WorkMethod, " +
            
"is {0}from the thread pool."
            Thread.CurrentThread.IsThreadPoolThread 
? "" : "not ");

        
// Signal that this thread is finished.
        ((AutoResetEvent)stateInfo).Set();
    }
}

执行结果是:ThreadTwo, executing WorkMethod, is from the thread pool.
ThreadOne, executing ThreadMethod, 
is not from the thread pool.

 

但是当我对这个例子稍作修改之后就出现了不可理解的问题,我在WorkMethod中加上Thread.Sleep让线程池中的线程休眠2秒,这样操作之后执行结果是:

执行结果
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->ThreadTwo, executing WorkMethod, is from the thread pool.
Sleep
ThreadOne, executing ThreadMethod, 
is not from the thread pool.
Sleep end

可以看出当线程池中的线程Sleep之后,被Join的thread即获得执行权,开始执行,这个似乎和msdn的解释有出入

另外我还做了一个测试,把另一个线程用Thread启动,而不是放在线程池中执行,看是否可以正常的阻塞线程,但是结果却是出人意料的,不能按预期阻塞,请看下面的实例代码:

Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->    class IsThreadPool
    {
        
static void Main()
        {
            AutoResetEvent autoEvent 
= new AutoResetEvent(false);

            Thread threadA 
=
                
new Thread(new ThreadStart(ThreadMethod));

            Thread threadB 
= new Thread(new ParameterizedThreadStart(WorkMethod));

            threadA.Start();

            
// Wait for foreground thread to end.
            threadA.Join();
            threadB.Start(autoEvent);



            
// Wait for background thread to end.
            autoEvent.WaitOne();


            Console.Read();
        }

        
static void ThreadMethod()
        {
            Console.WriteLine(
"ThreadOne, executing ThreadMethod, " +
                
"is {0}from the thread pool.",
                Thread.CurrentThread.IsThreadPoolThread 
? "" : "not ");
        }

        
static void WorkMethod(object stateInfo)
        {
            Console.WriteLine(
"ThreadTwo, executing WorkMethod, " +
                
"is {0}from the thread pool.",
                Thread.CurrentThread.IsThreadPoolThread 
? "" : "not ");
            
// Signal that this thread is finished.
            ((AutoResetEvent)stateInfo).Set();
        }
    }

不知道什么原因,上面的代码中threadA并没有被阻塞,难道是只能阻塞放在ThreadPool中执行的线程?没有道理,我反复做了实验都没有成功,把这个结果贴出来,请大家释疑。

好的,让我来回答你的问题。你想了解System.Threading序列的第一篇文章,它从Thread的线程单元状态ApartmentState说起。 Thread类在.NET Framework中是一个非常重要的类,它提供了一种在程序中创建管理线程的方式。在使用Thread类之前,我们需要了解线程单元状态(ApartmentState)。线程单元状态是指一个线程所在的单元,它决定了线程在运行时的行为。 在.NET Framework中,线程单元状态有两种:Single Threaded ApartmentMulti-Threaded Apartment。Single Threaded Apartment是指只有一个线程可以进入该单元,它适用于单线程的应用程序。Multi-Threaded Apartment是指多个线程可以进入该单元,它适用于多线程的应用程序。 在Thread类中,我们可以使用ApartmentState属性来设置线程单元状态。默认情况下,线程单元状态是Multi-Threaded Apartment。如果我们想将线程单元状态设置为Single Threaded Apartment,可以使用以下代码: ```csharp Thread t = new Thread(new ThreadStart(TestMethod)); t.SetApartmentState(ApartmentState.STA); t.Start(); ``` 在以上代码中,我们创建了一个新的线程,并将线程单元状态设置为Single Threaded Apartment。然后,我们启动线程并开始执行TestMethod方法。 总之,了解线程单元状态对于使用Thread类来创建管理线程是非常重要的。在下一篇文章中,我们将继续探讨System.Threading序列的内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值