如何:创建和终止线程

转载 2016年06月02日 14:13:26

https://msdn.microsoft.com/zh-cn/library/7a2f3ay4(v=vs.90).aspx

此示例演示如何创建辅助线程,并用它与主线程并行执行处理。还将演示如何使一个线程等待另一个线程,并正确地终止线程。有关多线程处理的背景信息,请参见托管线程处理使用线程处理(C# 编程指南)

该示例创建一个名为 Worker 的类,该类包含辅助线程将执行的方法 DoWork。这实际上是辅助线程的 Main 函数。辅助线程将通过调用此方法来开始执行,并在此方法返回时自动终止。DoWork 方法如下所示:

public void DoWork()
{
    while (!_shouldStop)
    {
        Console.WriteLine("worker thread: working...");
    }
    Console.WriteLine("worker thread: terminating gracefully.");
}


Worker 类包含另一个方法,该方法用于通知 DoWork 它应当返回。此方法名为 RequestStop,如下所示:

public void RequestStop()
{
    _shouldStop = true;
}


RequestStop 方法只是将 true 赋给 _shouldStop 数据成员。由于此数据成员由 DoWork 方法来检查,因此这会间接导致 DoWork 返回,从而终止辅助线程。但是,您应当注意:DoWork 和 RequestStop 将由不同线程执行。DoWork 由辅助线程执行,而 RequestStop 由主线程执行,因此_shouldStop 数据成员声明为 volatile,如下所示:

private volatile bool _shouldStop;


volatile 关键字用于通知编译器,将有多个线程访问 _shouldStop 数据成员,因此它不应当对此成员的状态做任何优化假设。有关更多信息,请参见volatile(C# 参考)

通过将 volatile 与 _shouldStop 数据成员一起使用,可以从多个线程安全地访问此成员,而不需要使用正式的线程同步技术,但这仅仅是因为_shouldStop 是 bool。这意味着只需要执行单个原子操作就能修改 _shouldStop。但是,如果此数据成员是类、结构或数组,那么,从多个线程访问它可能会导致间歇的数据损坏。假设有一个更改数组中的值的线程。Windows 会定期中断线程,以便允许其他线程执行。因此,此线程会在分配某些数组元素之后和分配其他元素之前被停止。由于数组现在有了一个程序员从不想要的状态,因此,读取此数组的另一个线程可能会失败。

在实际创建辅助线程之前,Main 函数会创建一个 Worker 对象和 Thread 的一个实例。线程对象被配置为:通过将对 Worker.DoWork 方法的引用传递给 Thread 构造函数,来将该方法用作入口点,如下所示:

Worker workerObject = new Worker();
Thread workerThread = new Thread(workerObject.DoWork);


此时,尽管辅助线程对象已存在并已配置,但尚未创建实际的辅助线程。只有当 Main 调用 Start 方法后,才会创建实际的辅助线程:

workerThread.Start();


此时,系统将启动辅助线程的执行,但这是在与主线程异步执行的。这意味着 Main 函数将在辅助线程进行初始化的同时继续执行代码。为了确保Main 函数不会尝试在辅助线程有机会执行之前将它终止,Main 函数将一直循环,直到辅助线程对象的 IsAlive 属性设置为 true

while (!workerThread.IsAlive);


下一步,通过调用 Sleep 来将主线程停止片刻。这确保了辅助线程的 DoWork 函数在 Main 函数执行其他任何命令之前,在 DoWork 方法内部执行若干次循环:

Thread.Sleep(1);


在 1 毫秒之后,Main 将通知辅助线程对象,它应当使用 Worker.RequestStop 方法(前面已介绍)自行终止:

workerObject.RequestStop();


还可以通过调用 Abort 从另一个线程中终止某个线程。这将强行终止受影响的线程,即使该线程尚未完成其任务,并且未提供清理资源的机会。此示例中显示的技术是首选方法。

最后,Main 函数对辅助线程对象调用 Join 方法。此方法导致当前线程阻塞或等待,直到对象所表示的线程终止。因此,直到辅助线程返回后,Join才会返回,然后自行终止:

workerThread.Join();


此时,只有执行 Main 的主线程还存在。它会显示一条最终消息,然后返回,从而使主线程也终止。

下面是完整的示例。

using System;
using System.Threading;

public class Worker
{
    // This method will be called when the thread is started.
    public void DoWork()
    {
        while (!_shouldStop)
        {
            Console.WriteLine("worker thread: working...");
        }
        Console.WriteLine("worker thread: terminating gracefully.");
    }
    public void RequestStop()
    {
        _shouldStop = true;
    }
    // Volatile is used as hint to the compiler that this data
    // member will be accessed by multiple threads.
    private volatile bool _shouldStop;
}

public class WorkerThreadExample
{
    static void Main()
    {
        // Create the thread object. This does not start the thread.
        Worker workerObject = new Worker();
        Thread workerThread = new Thread(workerObject.DoWork);

        // Start the worker thread.
        workerThread.Start();
        Console.WriteLine("main thread: Starting worker thread...");

        // Loop until worker thread activates.
        while (!workerThread.IsAlive);

        // Put the main thread to sleep for 1 millisecond to
        // allow the worker thread to do some work:
        Thread.Sleep(1);

        // Request that the worker thread stop itself:
        workerObject.RequestStop();

        // Use the Join method to block the current thread 
        // until the object's thread terminates.
        workerThread.Join();
        Console.WriteLine("main thread: Worker thread has terminated.");
    }
}


输出如下:

main thread: starting worker thread...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: terminating gracefully...
main thread: worker thread has terminated

C#终止线程的方法

微软的文档中不建议以Abort的方式终止线程。比如终止线程的瞬间,FileStream没有释放,会出现问题,等等。 Framework4.0提供了标准取消模式:协作式取消(Cooperative Ca...
  • qq_20161893
  • qq_20161893
  • 2017年11月01日 16:52
  • 832

C#多线程中子线程快速终止的几个处理办法

因项目需要,采用了多线程方案,其中主线程负责界面处理(如显示数据、与用户交互等),子线程负责读写串口(发送命令、读取数据)。但是,由于使用多线程的经验较少,对于关闭子线程的问题上走了一些弯路,在此留文...
  • EffectiveAgui
  • EffectiveAgui
  • 2012年08月08日 09:44
  • 18131

关于c# 中“正在终止线程”的问题

在C#中启用线程后,如果试图使用Abort方法来终止线程,那么必定会抛出“正在终止线程”的异常,一开始我也想过如何来避免这种异常出现,花了不少气力,但最后发现全是徒劳。   原因是一个正在运行的线...
  • heeye
  • heeye
  • 2014年05月07日 17:10
  • 6183

C# 中关闭当前线程的四种方式

转自:http://blog.csdn.net/yang1994/article/details/7947198 net类库已经帮助我们实现了窗口的关闭,如果此窗口是系统的主窗口,关闭此窗口即应...
  • u012252959
  • u012252959
  • 2016年01月12日 14:40
  • 10532

C#实现终止正在执行的线程

这篇文章主要介绍了C#实现终止正在执行的线程的方法,针对临界资源等容易出现错误的地方进行了分析,并提出了改进方案与实例,需要的朋友可以参考下. 本文实例讲述了C#实现终止正在执行的线程的实现...
  • zhu2695
  • zhu2695
  • 2016年12月05日 14:07
  • 3638

C#多线程中子线程快速终止的几个处理办法

因项目需要,采用了多线程方案,其中主线程负责界面处理(如显示数据、与用户交互等),子线程负责读写串口(发送命令、读取数据)。但是,由于使用多线程的经验较少,对于关闭子线程的问题上走了一些弯路,在此留文...
  • wyl19850608
  • wyl19850608
  • 2015年10月29日 11:18
  • 309

C#多线程开发2:线程挂起,恢复与中止等操作

在博文《C#多线程开发1:使用Thread类创建与启动线程》中介绍了线程的创建与启动。本文将在前文的基础之上,接着介绍线程的挂起,恢复与中止等操作。 首先回忆一下前文的知识点。 我们已经学习到: 1、...
  • tiana0
  • tiana0
  • 2013年09月22日 11:35
  • 14792

C#为什么不能强行终止线程

不知道是c#设计疏忽还是我没找到方对,.net一直无法强行线程子线程的操作不知道大家注意没有,如果子线程里有 死循环(有时间必须用循环)或子线程在进行一个阻塞式的操作,如影响队列里的消息,那么不能主线...
  • mojieqiong
  • mojieqiong
  • 2010年10月02日 15:16
  • 8234

【c#】关于终止以及删除主进程创建的线程以及进程的方法

今天在开发一款工具软件的时候,出现了一个问题:c#在Start新的Process之后,主动关闭窗口,在进程中发现窗口创建的另一个应用进程的优先级变为了主进程,导致了重启工具的时候,无法通过Proces...
  • z3237109
  • z3237109
  • 2015年08月27日 13:38
  • 1659

C#线程暂停与继续解决方案

C#线程暂停与继续解决方案            昨天, 老师要我们每个人交一个关于黑客方面的程序,想了半天发现端口扫描工具好像好写点,从昨天写到今天基本快完成了,给大家看下效果,不要笑话我哦哦(~...
  • xiaohui_hubei
  • xiaohui_hubei
  • 2012年04月24日 16:59
  • 9030
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何:创建和终止线程
举报原因:
原因补充:

(最多只允许输入30个字)