如何:创建和终止线程(C# 编程指南)

本文介绍了如何在C#中创建并优雅地终止辅助线程。通过使用Worker类及其DoWork方法作为线程入口点,结合RequestStop方法来通知线程停止运行。此外,文章还讨论了线程同步及安全访问共享变量的最佳实践。

转:http://msdn.microsoft.com/zh-cn/library/7a2f3ay4.aspx

 今天遇到一个问题,看了这篇文章解决了。

问题:怎样结束指定的某个线程。

解决办法:我先把它存入 Dictionary<String, Thread>,然后按key取出,再调用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 返回,从而终止辅助线程。但是,您应当注意:DoWorkRequestStop 将由不同线程执行。DoWork 由辅助线程执行,而RequestStop 由主线程执行,因此 _shouldStop 数据成员声明为volatile,如下所示:

C#
private volatile bool _shouldStop;


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

通过将 volatile _shouldStop 数据成员一起使用,可以从多个线程安全地访问此成员,而不需要使用正式的线程同步技术,但这仅仅是因为 _shouldStopbool。这意味着只需要执行单个原子操作就能修改_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.");
    }
}


输出如下:

other
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
 
专利质押一种融资担保商业活动,由专利权人债权人协商一致后,共同向国家知识产权局申请办理。为债务提供担保,以便获得融资。未经质权人同意,出质人不得转让或许可他人使用该专利。包括发明授权、外观设计、实用新型专利质押数据。数据量60万条。数据指标序号 标题 (中文) 标题 (英文) 摘要 (中文) 摘要 (英文) 申请人 公开(公告)号 公开(公告)日 申请号 申请日 公开类型 专利类型 公开国别 标题(小语种原文) 摘要(小语种原文) 首项权利要求 首权翻译 独立权利要求 权利要求数量 独立权利要求数量 从属权利要求数量 文献页数 首权字数 技术功效句 技术功效短语 技术功效1级 技术功效2级 技术功效3级 技术功效TRIZ参数 用途 IPC主分类 IPC 洛迦诺分类号 EC CPC UC FI F-term 国民经济分类 国民经济行业() 新兴产业分类 新兴产业() 知识密集型分类 学科分类 清洁能源产业 清洁生产产业 数字经济核心产业 申请人(翻译) 申请人(其他) 申请人终属母公司(中文) 申请人终属母公司(英文) 标准化申请人 标准化当前权利人 当前权利人 第一申请人 申请人数量 申请人类型 申请人国家/地区 申请人地址 申请人地址(其他) 申请人省市代码 中国申请人地市 中国申请人区县 当前专利权人地址 工商别名 工商英文名 工商注册地址 工商公司类型 工商成立日期 工商统一社会信用代码 工商注册号 工商上市代码 工商企业状态 发明人 发明(设计)(其他) 第一发明(设计)人 当前发明人名称 发明(设计)人数量 发明人国家/地区 发明人地址(原始) 发明(设计)人地址(其他) 代理机构 代理人 审查员 转让人地址 受让人地址 EP指定生效国 引证专利 被引证专利 自引信息 他引信息 被自引信息 被他引信息 家族引证 家族被引证 引证申请人 被引证申请人 家族引证申请人 家族被引证申请人 引证次数 被引证次数 自引次数 他引次数 被自引次数 被他引次数 家族引证次数 家族被引证次数 引证科技文献 引证类别 被引证类别 引证来源 被引证来源 被引证国别(forward) 简单同族 扩展同族 DocDB同族 简单同族ID 扩展同族ID DocDB同族ID 简单同族个数 扩展同族个数 DocDB同族个数 同族国家/地区 优先权信息 优先权号 优先权日 最早优先权日 优先权国别 PCT国际申请号 PCT国际公布号 PCT进入国家阶段日 母案 分案 一案双申 专利有效性 当前法律状态 法律状态 法律文书日期 法律文书编号 复审请求人 无效请求人 复审无效决定 复审无效决定日 复审无效法律依据 转让次数 转让执行日 转让人 转让人类型 受让人 受让人类型 标准受让人 许可次数 许可合同备案日期 许可人 许可人类型 被许可人 被许可人类型 当前被许可人 许可类型 质押次数 出质人 质权人 当前质权人 诉讼次数 原告 被告 诉讼类型 法庭 海关备案 复审决定日 无效决定日 口审日期 法律事件 复审请求日 许可合同备案号 质押号 转让登记号 转让登记日 当前权利人类型 首次公开号 首次公开日 授权公告号 授权公告日 实质审查生效日 进入实质审查时长 审查时长 失效日 专利寿命(月) 标准类型 标准项目 标准号 公司(标准) 合享价值度 技术稳定性 技术先进性 保护范围 文献种类代码 预估到期日 奖励名称 奖励届次 奖励等级 DWPI标题 DWPI用途 DWPI优势 DWPI新颖性 DWPI详细描述 DWPI生物活性 DWPI生物学机制 DWPI技术要点 DWPI分类号 DWPI手工代码 DWPI同族专利 DWPI同族国家/地区 DWPI同族ID DWPI专利权人/申请人 DWPI发明人 DWPI优先权国别-最早 DWPI优先权号 DWPI优先权国别
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值