分享

C# ThreadPool.QueueUserWorkItem典型案例详解

 ThinkTank_引擎 2016-05-01

   using System;

  using System.Collections.Generic;

  using System.Threading;

  namespace ThreadPoolTest

  {

  class Program

  {

  static void Main(string[] args)

  {

  //声明一个Action委托的List,添加一些委托测试用

  List actions = new List

  {

  ()=>{Console.WriteLine("A-1");},

  ()=>{Console.WriteLine("A-2");},

  ()=>{Console.WriteLine("A-3");},

  ()=>{Console.WriteLine("A-4");}

  };

  //遍历输出结果

  foreach (var action in actions)

  {

  ThreadPool.QueueUserWorkItem(state => action() , null);

  }

  Console.ReadKey();

  }

  }

  }

  这个很意外的结果如下:

C# ThreadPool.QueueUserWorkItem典型案例详解 三联

  为什么如此呢:

  我分析下,首先大家都知道创建一个线程是需要时间的,线程池作为一个管理线程的对象操作简单,但是涉及到具体细节的时候却很难控制,其原理是当线程池收到请求以后,则从线程池中找到一个闲的线程分配给它,然后启动。 但是线程池的线程从创建到启动需要时间,但是主线程的循环显然只是瞬间完成,完全没必要夹杂在线程池的等待中,因此出现了主线程执行完循环最后是的线程池收到的请求委托是列表中的最后一个,如何解决?

  方式一: Thread.Sleep(1);

  博主说对于Thread.Sleep(N)的方式难以接受,其实只要细细去分析原理,就能知道这个方式是可以接受甚至是微妙的,Thread.Sleep(N)是对当前线程阻塞一定时间,那这个处理不论是主线程还是线程池中的线程都是有效果的,至少为线程池中的线程的请求与启动赢得了时间。当然在这里阻塞的线程一定是主线程,使其不能得到CPU时间,这样也就成功了得到预期结果。

  后来又采取另外一种方式,

  方式二:

  foreach (var action in actions)

  {

  var Tempaction = action;

  ThreadPool.QueueUserWorkItem(state => Tempaction() , null);

  }

  将循环中的变量存储到一个临时变量中,为什么这样行呢?

  大家知道线程池是有请求就为其分配一个自由线程与其工作,当每一次循环中的变量不同也就是对象不同时这时候每次请求出现差异,当然线程池必须为每一个做准备,不同于把循环变量直接作为请求,这时候每一个请求就按顺序依次准备好依次启动。当然也就成功了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多