线程池ThreadPool操作

一.CLR线程池并不会在CLR初始化时立即建立线程,而是在应用程序要创建线程来运行任务时,线程池才初始化一个线程。

 //通过CLR线程池所建立的线程总是默认为后台线程,优先级数为ThreadPriority.Normal。

1.线程池初始化时是没有线程的,线程池里的线程的初始化与其他线程一样,但是在完成任务以后,该线程不会自行销毁,而是以挂起的状态返回到线程池。

2.直到应用程序再次向线程池发出请求时,线程池里挂起的线程就会再度激活执行任务。

3.这样既节省了建立线程所造成的性能损耗,也可以让多个任务反复重用同一线程,从而在应用程序生存期内节约大量开销。

二.CLR线程池分为工作者线程(workerThreads)与I/O线程(completionPortThreads)两种:

1.工作者线程是主要用作管理CLR内部对象的运作,通常用于计算密集的任务。

2.I/O(Input/Output)线程主要用于与外部系统交互信息,如输入输出,CPU仅需在任务开始的时候,将任务的参数传递给设备,然后启动硬件设备即可。

三.使用CLR线程池的工作者线程一般有两种方式:

1.通过ThreadPool.QueueUserWorkItem()方法;

(1)ThreadPool线程池中有两个重载的静态方法可以直接启动工作者线程:

ThreadPool.QueueUserWorkItem(WaitCallback(方法名));

//启动工作者线程(无参数)
 ThreadPool.QueueUserWorkItem(new WaitCallback(RunMyMethod));

ThreadPool.QueueUserWorkItem(new WaitCallback(方法名),Object对象参数);

使用第二个重载方法ThreadPool.QueueUserWorkItem(WaitCallback,object)方法可以把object对象作为参数传送到回调函数中。

//启动工作者线程(有参数 obj类型)
 ThreadPool.QueueUserWorkItem(new WaitCallback(MyMethod), Obj);
void MyMethod(object Obj){//..}

WaitCallback委托指向的必须是一个带有object参数的无返回值方法,传递多个参数只有通过委托

2.通过委托;

使用BeginInvoke与EndInvoke委托异步调用线程

建立一个委托对象,通过IAsyncResult BeginInvoke(string name,AsyncCallback callback,object state)异步调用委托方法,BeginInvoke方法除最后的两个参数外,其他参数都是与方法参数相对应的。

利用EndInvoke(IAsyncResult--上一步BeginInvoke返回的对象)方法就可以结束异步操作,获取委托的运行结果。

//声明委托
//delegate string MyDelegate(string Name,int Age);
//建立委托
MyDelegate myDelegate = new MyDelegate(GetInfo);
//异步调用委托,除最后两个参数外,前面的参数都可以传进去
IAsyncResult result = myDelegate.BeginInvoke("小明",18, null, null);  //IAsynResult还能轮询判断
//调用EndInvoke(IAsyncResult)获取运行结果
string data = myDelegate.EndInvoke(result);
//调用的方法
private string GetInfo(string Name,int Age)
{
   return string.Format("我是{0},今年{1}岁!",name,age);
}
要注意的是并不知道异步操作什么时候执行完,什么时候开始调用EndInvoke,因为一旦EndInvoke主线程就会处于阻塞等待状态。这时需要用到IAsyncResult提高主线程的工作性能
//IAsyncResult属性
public interface IAsyncResult
{
  object AsyncState {get;}       //获取用户定义的对象,它限定或包含关于异步操作的信息。
  WailHandle AsyncWaitHandle {get;}  //获取用于等待异步操作完成的 WaitHandle。
  bool CompletedSynchronously {get;} //获取异步操作是否同步完成的指示。
  bool IsCompleted {get;}        //获取异步操作是否已完成的指示。
}
//利用IsCompleted属性,来判断异步线程是否完成
while (!result.IsCompleted)
{
      Thread.Sleep(500);          
      Console.WriteLine("异步线程还没完成,主线程干其他事!");
 }
//除了IsCompleted属性外,还可以使用AsyncWaitHandle如下3个方法实现同样轮询判断效果
//WaitOne:判断单个异步线程是否完成;
//WaitAny:判断是否异步线程是否有指定数量个已完成;
//WaitAll:判断是否所有的异步线程已完成;
//WaitOne:
 //比上个例子,判断条件由IsCompleted属性换成了AsyncWaitHandle,仅此而已
  while (!result.AsyncWaitHandle.WaitOne(200))
  {
      Console.WriteLine("异步线程没完,主线程继续干活!");
  }
//WaitAny:
 //是否完成了指定数量
  WaitHandle[] waitHandleList = new WaitHandle[] { result.AsyncWaitHandle };
  while (WaitHandle.WaitAny(waitHandleList, 200) > 0)
  {
      Console.WriteLine("异步线程完成数未大于0,主线程继续甘其他事!");
  }
//WaitAll:
WaitHandle[] waitHandleList = new WaitHandle[] { result.AsyncWaitHandle };
  //是否全部异步线程完成
  while (!WaitHandle.WaitAll(waitHandleList, 200))
  {
      Console.WriteLine("异步线程未全部完成,主线程继续干其他事!");
  }
//IAsyncResult回调函数
//倒数第二个参数,委托中绑定了完成后的回调方法
IAsyncResult result1 = myDelegate.BeginInvoke("小明",23, new AsyncCallback(Completed), null);
//供异步线程完成回调的方法
        static void Completed(IAsyncResult result)
        {
            //获取委托对象,调用EndInvoke方法获取运行结果
            AsyncResult _result = (AsyncResult)result;
            MyDelegate myDelegaate = (MyDelegate)_result.AsyncDelegate;
            //获得参数
            string data = myDelegaate.EndInvoke(_result);
            Console.WriteLine(data);
            //异步线程执行完毕
            Console.WriteLine("异步线程完成咯!");
            Console.WriteLine("回调函数也是由" + Thread.CurrentThread.Name + "调用的!");
        }
    }
//回调函数依然是在辅助线程中执行的,这样就不会影响主线程的运行。
//线程池的线程默认是后台线程。但是如果主线程比辅助线程优先完成,那么程序已经卸载,回调函数未必会执行。如果不希望丢失回调函数中的操作,要么把异步线程设为前台线程,要么确保主线程将比辅助线程迟完成。

//BeginInvoke("刘备",23, new AsyncCallback(Completed), null)最后一个参数用来传参
Person p = new Person(2,"关羽");
IAsyncResult result1 = myDelegate.BeginInvoke("刘备", 23, new AsyncCallback(Completed), p);
//供异步线程完成回调的方法
        static void Completed(IAsyncResult result)
        {
            //获取委托对象,调用EndInvoke方法获取运行结果
            AsyncResult _result = (AsyncResult)result;
            MyDelegate myDelegaate = (MyDelegate)_result.AsyncDelegate;
            //获得参数
            string data = myDelegaate.EndInvoke(_result);
            Console.WriteLine(data);

            Person p = result.AsyncState as Person;
            Console.WriteLine("传过来的参数是:" + p.Name);
            //异步线程执行完毕
            Console.WriteLine("异步线程完成咯!");
            Console.WriteLine("回调函数也是由" + Thread.CurrentThread.Name + "调用的!");
        }

  

 

posted @ 2016-07-22 18:04  会弹猫的吉他  阅读(348)  评论(0编辑  收藏  举报