如何:创建和终止线程
2016-06-02 14:13
453 查看
https://msdn.microsoft.com/zh-cn/library/7a2f3ay4(v=vs.90).aspx
此示例演示如何创建辅助线程,并用它与主线程并行执行处理。还将演示如何使一个线程等待另一个线程,并正确地终止线程。有关多线程处理的背景信息,请参见托管线程处理和使用线程处理(C#
编程指南)。
该示例创建一个名为 Worker 的类,该类包含辅助线程将执行的方法 DoWork。这实际上是辅助线程的 Main 函数。辅助线程将通过调用此方法来开始执行,并在此方法返回时自动终止。DoWork 方法如下所示:
C#
Worker 类包含另一个方法,该方法用于通知 DoWork 它应当返回。此方法名为 RequestStop,如下所示:
C#
RequestStop 方法只是将 true 赋给 _shouldStop 数据成员。由于此数据成员由 DoWork 方法来检查,因此这会间接导致 DoWork 返回,从而终止辅助线程。但是,您应当注意:DoWork 和 RequestStop 将由不同线程执行。DoWork 由辅助线程执行,而 RequestStop 由主线程执行,因此_shouldStop 数据成员声明为 volatile,如下所示:
C#
volatile 关键字用于通知编译器,将有多个线程访问 _shouldStop 数据成员,因此它不应当对此成员的状态做任何优化假设。有关更多信息,请参见volatile(C#
参考)。
通过将 volatile 与 _shouldStop 数据成员一起使用,可以从多个线程安全地访问此成员,而不需要使用正式的线程同步技术,但这仅仅是因为_shouldStop 是 bool。这意味着只需要执行单个原子操作就能修改 _shouldStop。但是,如果此数据成员是类、结构或数组,那么,从多个线程访问它可能会导致间歇的数据损坏。假设有一个更改数组中的值的线程。Windows
会定期中断线程,以便允许其他线程执行。因此,此线程会在分配某些数组元素之后和分配其他元素之前被停止。由于数组现在有了一个程序员从不想要的状态,因此,读取此数组的另一个线程可能会失败。
在实际创建辅助线程之前,Main 函数会创建一个 Worker 对象和 Thread 的一个实例。线程对象被配置为:通过将对 Worker.DoWork 方法的引用传递给 Thread 构造函数,来将该方法用作入口点,如下所示:
C#
此时,尽管辅助线程对象已存在并已配置,但尚未创建实际的辅助线程。只有当 Main 调用 Start 方法后,才会创建实际的辅助线程:
C#
此时,系统将启动辅助线程的执行,但这是在与主线程异步执行的。这意味着 Main 函数将在辅助线程进行初始化的同时继续执行代码。为了确保Main 函数不会尝试在辅助线程有机会执行之前将它终止,Main 函数将一直循环,直到辅助线程对象的 IsAlive 属性设置为 true:
C#
下一步,通过调用 Sleep 来将主线程停止片刻。这确保了辅助线程的 DoWork 函数在 Main 函数执行其他任何命令之前,在 DoWork 方法内部执行若干次循环:
C#
在 1 毫秒之后,Main 将通知辅助线程对象,它应当使用 Worker.RequestStop 方法(前面已介绍)自行终止:
C#
还可以通过调用 Abort 从另一个线程中终止某个线程。这将强行终止受影响的线程,即使该线程尚未完成其任务,并且未提供清理资源的机会。此示例中显示的技术是首选方法。
最后,Main 函数对辅助线程对象调用 Join 方法。此方法导致当前线程阻塞或等待,直到对象所表示的线程终止。因此,直到辅助线程返回后,Join才会返回,然后自行终止:
C#
此时,只有执行 Main 的主线程还存在。它会显示一条最终消息,然后返回,从而使主线程也终止。
下面是完整的示例。
示例
C#
输出如下:
请参见
“线程”示例
C# 编程指南
线程处理(C# 编程指南)
使用线程处理(C# 编程指南)
Thread
volatile(C# 参考)
Mutex
Monitor
Start
IsAlive
Sleep
Join
Abort
托管线程处理
线程示例
此示例演示如何创建辅助线程,并用它与主线程并行执行处理。还将演示如何使一个线程等待另一个线程,并正确地终止线程。有关多线程处理的背景信息,请参见托管线程处理和使用线程处理(C#
编程指南)。
该示例创建一个名为 Worker 的类,该类包含辅助线程将执行的方法 DoWork。这实际上是辅助线程的 Main 函数。辅助线程将通过调用此方法来开始执行,并在此方法返回时自动终止。DoWork 方法如下所示:
C#
public void DoWork() { while (!_shouldStop) { Console.WriteLine("worker thread: working..."); } Console.WriteLine("worker thread: terminating gracefully."); }
Worker 类包含另一个方法,该方法用于通知 DoWork 它应当返回。此方法名为 RequestStop,如下所示:
C#
public void RequestStop() { _shouldStop = true; }
RequestStop 方法只是将 true 赋给 _shouldStop 数据成员。由于此数据成员由 DoWork 方法来检查,因此这会间接导致 DoWork 返回,从而终止辅助线程。但是,您应当注意:DoWork 和 RequestStop 将由不同线程执行。DoWork 由辅助线程执行,而 RequestStop 由主线程执行,因此_shouldStop 数据成员声明为 volatile,如下所示:
C#
private volatile bool _shouldStop;
volatile 关键字用于通知编译器,将有多个线程访问 _shouldStop 数据成员,因此它不应当对此成员的状态做任何优化假设。有关更多信息,请参见volatile(C#
参考)。
通过将 volatile 与 _shouldStop 数据成员一起使用,可以从多个线程安全地访问此成员,而不需要使用正式的线程同步技术,但这仅仅是因为_shouldStop 是 bool。这意味着只需要执行单个原子操作就能修改 _shouldStop。但是,如果此数据成员是类、结构或数组,那么,从多个线程访问它可能会导致间歇的数据损坏。假设有一个更改数组中的值的线程。Windows
会定期中断线程,以便允许其他线程执行。因此,此线程会在分配某些数组元素之后和分配其他元素之前被停止。由于数组现在有了一个程序员从不想要的状态,因此,读取此数组的另一个线程可能会失败。
在实际创建辅助线程之前,Main 函数会创建一个 Worker 对象和 Thread 的一个实例。线程对象被配置为:通过将对 Worker.DoWork 方法的引用传递给 Thread 构造函数,来将该方法用作入口点,如下所示:
C#
Worker workerObject = new Worker(); Thread workerThread = new Thread(workerObject.DoWork);
此时,尽管辅助线程对象已存在并已配置,但尚未创建实际的辅助线程。只有当 Main 调用 Start 方法后,才会创建实际的辅助线程:
C#
workerThread.Start();
此时,系统将启动辅助线程的执行,但这是在与主线程异步执行的。这意味着 Main 函数将在辅助线程进行初始化的同时继续执行代码。为了确保Main 函数不会尝试在辅助线程有机会执行之前将它终止,Main 函数将一直循环,直到辅助线程对象的 IsAlive 属性设置为 true:
C#
while (!workerThread.IsAlive);
下一步,通过调用 Sleep 来将主线程停止片刻。这确保了辅助线程的 DoWork 函数在 Main 函数执行其他任何命令之前,在 DoWork 方法内部执行若干次循环:
C#
Thread.Sleep(1);
在 1 毫秒之后,Main 将通知辅助线程对象,它应当使用 Worker.RequestStop 方法(前面已介绍)自行终止:
C#
workerObject.RequestStop();
还可以通过调用 Abort 从另一个线程中终止某个线程。这将强行终止受影响的线程,即使该线程尚未完成其任务,并且未提供清理资源的机会。此示例中显示的技术是首选方法。
最后,Main 函数对辅助线程对象调用 Join 方法。此方法导致当前线程阻塞或等待,直到对象所表示的线程终止。因此,直到辅助线程返回后,Join才会返回,然后自行终止:
C#
workerThread.Join();
此时,只有执行 Main 的主线程还存在。它会显示一条最终消息,然后返回,从而使主线程也终止。
下面是完整的示例。
C#
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# 编程指南
参考
线程处理(C# 编程指南)使用线程处理(C# 编程指南)
Thread
volatile(C# 参考)
Mutex
Monitor
Start
IsAlive
Sleep
Join
Abort
其他资源
托管线程处理线程示例
相关文章推荐
- java web taglib自定义标签的练习
- 【Android新手笔记四】activity之间的数据共享
- ionic ng-src 在网页显示,但是导出apk在android手机中运行不显示图片
- 跨域请求带cookie的解决方案
- uiscrollview滚动时候nstimer会失灵
- opencv-ios开发笔记7 神经网络 分类器
- 安卓原生时间选择器,DatePicker和TimePicker并用,弹窗dialog
- PHPexcel导入导出超过26列的解决方法
- 通过代理推送数据到Salesforce
- MVP架构
- 我有几个粽子,和一个故事
- Dashgo D1软件支持
- FZU 2230 翻翻棋 (找规律 水题)
- 剑指offer(1)-二维数组中的查找
- myeclipse项目过大打开弹警告窗口
- Android设备中实现陀螺仪(Orientation Sensor)
- Ant 风格路径表达式
- Android开发实战总结--编程规范(持续更新中...)
- 欢迎使用CSDN-markdown编辑器
- 数据库sql判断语句(case,IF)