多线程编程笔记(二)
线程池
用线程池编写多线程应用一般步骤:
1、编写工作任务:将所有的工作任务泛放在一个符合WaitCallback接口的函数中
public static void MyAsyncOperation(object state)
{
//...
//要完成的工作任务
}
一般通过state传入一个同步对象
2、往线程池中添加工作项
ThreadPool.QueueUserWorkItem(new WaitCallback(MyAsyncOperation),asyncOpIsDone);
此时将第2个参数asyncOpIsDone作为MyAsyncOperation的state参数执行该委托实例。
3、和工作线程通信
比较典型的做法是主线程传入一个同步对象到工作线程,工作线程在完成任务后利用传入的同步对象通知主线程。
线程池中的线程是按需创建达到。公共运行库根据线程池中工作任务的多少创建合适的线程来处理工作任务。
注意:为了减轻系统的负担,应尽量使每个工作任务尽快的结束。对于那些需要大量CPU时间的工作任务,可利用Thread类创建自由线程来执行。
例程:
using System;
using System.Threading;
namespace AsyncMethod
{
class App
{
public static void MyAsyncOperation(object state)
{
Console.WriteLine("工作任务");
//....
Console.WriteLine("睡眠5秒");
Thread.Sleep(5000);
((AutoResetEvent)state).Set();//将指定事件的状态设置为终止。指示工作认为已完成
Console.WriteLine("工作任务结束");
}
public static void Main()
{
Console.WriteLine("主线程进行异步调用");
AutoResetEvent asyncOpIsDone = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(MyAsyncOperation),asyncOpIsDone);
Console.WriteLine("主线程执行其他任务");
//....
Console.WriteLine("主线程等待工作任务结束");
asyncOpIsDone.WaitOne();//阻塞当前线程,直到当前的 WaitHandle 收到信号。
}
}
}
//下面程序,工作线程和主线程均在同一个应用域中,公共运行库创建了2个工作线程来完成工作线程池中的2个任务。
using System;
using System.Threading;
namespace demoThreadPool
{
class App
{
public static void MyWorkItem(object state)
{
Console.WriteLine("/n当前线程的代码:{0}",Thread.CurrentThread.GetHashCode().ToString());
Console.WriteLine("当前应用域的名称为:{0}",AppDomain.CurrentDomain.FriendlyName);
Thread.Sleep(1000);
((AutoResetEvent)state).Set();
}
public static void demoThreadPool()
{
Console.WriteLine("当前线程的代码:{0}",Thread.CurrentThread.GetHashCode().ToString());
Console.WriteLine("当前应用域的名称为:{0}",AppDomain.CurrentDomain.FriendlyName);
AutoResetEvent asyncOpIsDone = new AutoResetEvent(false);
AutoResetEvent asyncOpIsDone2 = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(MyWorkItem),asyncOpIsDone);
ThreadPool.QueueUserWorkItem(new WaitCallback(MyWorkItem),asyncOpIsDone2);
WaitHandle[] handles= new WaitHandle[2];
handles[0] = asyncOpIsDone;
handles[1] = asyncOpIsDone2;
WaitHandle.WaitAll(handles);//此语句也可以用下面语句代替
//handles[0].WaitOne();
//handles[1].WaitOne();
}
public static void Main()
{
demoThreadPool();
}
}
}
方法说明:
public AutoResetEvent(
bool initialState
);
//用一个指示是否将初始状态设置为终止的布尔值初始化 AutoResetEvent 类的新实例。
//initialState
//如果为 true,则将初始状态设置为终止;如果为 false,则将初始状态设置为非终止。
//使用 AutoResetEvent 类可以使某个线程等待,直到某个事件通过调用 AutoResetEvent.Set 将其置于已发信号的状态为止。与 ManualResetEvent 不同,AutoResetEvent 在单个等待线程被释放后由系统自动重置为未发信号的状态。如果没有任何线程正在等待,则该事件对象的状态将保持已发信号的状态。AutoResetEvent 与 Win32 CreateEvent 调用相对应,并将 bManualReset 参数指定为 false。
//还要注意WaitOne,WaitAll,WaitAny的用法
<.net核心技术-原理与架构>