您的位置:首页 > 编程语言 > C#

C# Tip -- 如何优雅的控制线程状态

2011-04-06 22:09 513 查看
先问读者一个问题,如果想控制一个线程(Thread)挂起,继续,结束你会优先选择如何处理?

从面试的经验来看,多数的面试者都会说Thread不是提供了Suspend,Resume,Abort等方法吗,直接调用就好了,简单快捷.但很多情况下简单就是美只是一个谎言而已.

Suspend和Resume方法已经被MS标注过时(Obsolete),不建议用户使用,MS同时推荐通过同步控制来管理线程状态.

再问读者一个问题,如果控制一个线程池中的线程的挂起,继续,结束你会优先选择如何处理?

也许有人会说,既然没法用API了,那我定义一些标志量,来做状态控制不就可以了吗?

确实,说起来很简单.那么变量的值需不需要考虑由于多线程问题导致的读写问题呢,你会怎么处理?

如果不用标志量,可以用同步事件来做,会不会更优雅一些呢?

让我把传统的方式以及使用同步方式做的控制都写一遍,让读者来做取舍吧.

代码如下,注释也比较全,就不再累述细节.

class Program

{

static void Main(string[] args)

{

UseThreadAPI();

UseSyncEvent();

UseThreadPool();

UseSyncEventThreadPool();

Console.WriteLine("All tests finished");

Console.ReadKey();

}

/// <summary>

/// 使用标准Thread API来控制线程状态,

/// Suspend和Resume是过时的方法,MS不推荐使用

/// MS推荐的方式就是后面要提到的使用Monitor,Event等做同步控制.

/// </summary>

static void UseThreadAPI()

{

Console.WriteLine("----------Use thread API----------");

Thread t = new Thread(

new ThreadStart(() =>

{

while (true)

{

Console.WriteLine("Now Date:{0}", DateTime.Now);

Thread.Sleep(1000);

}

}

));

t.Start();

//暂停线程执行

Console.ReadKey();

t.Suspend();

Console.WriteLine("Thread suspended");

//继续线程执行

Console.ReadKey();

t.Resume();

Console.WriteLine("Thread resumed");

//结束线程

Console.ReadKey();

t.Abort();

Console.WriteLine("Thread aborted");

Console.ReadKey();

}

/// <summary>

/// 使用Event做同步控制

/// 三个Event组合使用就可以产生同Suspend,Resuem,Abort相同的效果

/// 而且你可以控制Abort的时机以及并作出适当的处理

/// 而不是像Thread.Abort一样通过异常的方式结束线程

/// </summary>

static void UseSyncEvent()

{

Console.WriteLine("----------Use sync event----------");

AutoResetEvent evtPause = new AutoResetEvent(false);

AutoResetEvent evtResume = new AutoResetEvent(false);

AutoResetEvent evtStop = new AutoResetEvent(false);

Thread t = new Thread(

new ThreadStart(() =>

{

//WaitOne(1000),可产生Sleep(1000)相同的效果

//如果eveStop被置位,则立即返回True,跳出循环

//如果等待1000ms超时,则返回False,继续循环

while (!evtStop.WaitOne(1000))

{

//WaitOne(0)可立即判断evtPase有没有被置位

//如果置位,进入暂停状态,等待Resume被置位才会恢复线程执行

if (evtPause.WaitOne(0))

{

//WaitOne()不带参数表示一直等待,直到被置位

evtResume.WaitOne();

}

Console.WriteLine("Now Date:{0}", DateTime.Now);

}

}

));

t.Start();

//暂停线程执行

Console.ReadKey();

evtPause.Set();

Console.WriteLine("Thread suspended");

//继续线程执行

Console.ReadKey();

evtResume.Set();

Console.WriteLine("Thread resumed");

//结束线程

Console.ReadKey();

evtStop.Set();

Console.WriteLine("Thread stopped");

Console.ReadKey();

}

class ThreadStatusController

{

/// <summary>

/// 声明为volatile可以避免用lock进行加锁同步

/// 编译器自己会做优化

/// 另外不能声明属性为volatile,因此只能作为成员变量放出.

/// </summary>

public volatile bool IsPauseRequired;

public volatile bool IsStopRequired;

}

/// <summary>

/// 对于放入线程池的进程,是无法通过Thread的API进行控制的

/// 通常的做法是通过一些bool量做控制,这不是优雅的解决方案.

/// </summary>

static void UseThreadPool()

{

Console.WriteLine("----------Use thread pool----------");

var tsc = new ThreadStatusController();

ThreadPool.QueueUserWorkItem(status =>

{

var ctrl = status as ThreadStatusController;

//等待IsStopRequired标志量的值为True

while (!ctrl.IsStopRequired)

{

//如果不是Pause请求,则执行

if (!ctrl.IsPauseRequired)

Console.WriteLine("Now Date:{0}", DateTime.Now);

Thread.Sleep(1000);

}

}, tsc);

//暂停线程执行

Console.ReadKey();

tsc.IsPauseRequired = true;

Console.WriteLine("Thread suspended");

//继续线程执行

Console.ReadKey();

tsc.IsPauseRequired = false;

Console.WriteLine("Thread resumed");

//结束线程

Console.ReadKey();

tsc.IsStopRequired = true;

Console.WriteLine("Thread aborted");

Console.ReadKey();

}

/// <summary>

/// 声明三个同步事件分别对应三种同步状态

/// </summary>

class ThreadStatusEventController

{

public ThreadStatusEventController()

{

PauseEvent = new AutoResetEvent(false);

ResumeEvent = new AutoResetEvent(false);

StopEvent = new AutoResetEvent(false);

}

public AutoResetEvent PauseEvent { get; set; }

public AutoResetEvent ResumeEvent { get; set; }

public AutoResetEvent StopEvent { get; set; }

}

static void UseSyncEventThreadPool()

{

Console.WriteLine("----------Use sync event with thread pool----------");

var tsc = new ThreadStatusEventController();

ThreadPool.QueueUserWorkItem(status =>

{

var ctrl = status as ThreadStatusEventController;

//控制代码跟采用Thread的方式类似,不累述

while (!ctrl.StopEvent.WaitOne(1000))

{

if (ctrl.PauseEvent.WaitOne(0))

{

ctrl.ResumeEvent.WaitOne();

}

Console.WriteLine("Now Date:{0}", DateTime.Now);

}

}, tsc);

//暂停线程执行

Console.ReadKey();

tsc.PauseEvent.Set();

Console.WriteLine("Thread suspended");

//继续线程执行

Console.ReadKey();

tsc.ResumeEvent.Set();

Console.WriteLine("Thread resumed");

//结束线程

Console.ReadKey();

tsc.StopEvent.Set();

Console.WriteLine("Thread aborted");

Console.ReadKey();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: