<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_一棵大树</title><subtitle type="text">如果有人问我下辈子想做什么？我会回答：“一棵树”因为没有离别，没有改变 ……就算枯朽，也不会离开我熟悉的一切。。。和我的爱人、朋友永远在一起，哪怕只能遥遥相望。。。偶尔想想远方。。。</subtitle><id>http://feed.cnblogs.com/blog/u/11415/rss</id><updated>2012-03-22T05:48:57Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/11415/rss"/><entry><id>http://www.cnblogs.com/asyuras/archive/2012/03/22/2411513.html</id><title type="text">VS2010中Parallel的使用</title><summary type="text">原文地址：http://tech.it168.com/a2010/0318/862/000000862631.shtml作者：IT168 陈良乔 【IT168 专稿】书接上回。在前一篇“Visual Studio 2010对并行计算的支持”文章中，我们介绍了如何利用Parallel.For和Parallel.ForEach函数来并行化for循环和foreach循环。实际上，Parallel.For和Parallel.ForEach函数主要是针对“并行数据”的并行化操作，所谓并行数据，就是整个数据集中数据单元是相互独立的，可以同时进行处理。在实际开发中，我们遇到的可以并行处理的不仅包括“并行数.</summary><published>2012-03-22T05:47:00Z</published><updated>2012-03-22T05:47:00Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><link rel="alternate" href="http://www.cnblogs.com/asyuras/archive/2012/03/22/2411513.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/archive/2012/03/22/2411513.html"/><content type="html">&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;span&gt;原文地址：&lt;a href="http://tech.it168.com/a2010/0318/862/000000862631.shtml"&gt;http://tech.it168.com/a2010/0318/862/000000862631.shtml&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;作者：IT168 陈良乔&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;【&lt;/span&gt;&lt;strong&gt;IT168 专稿&lt;/strong&gt;&lt;span&gt;】书接上回。在前一篇&amp;ldquo;&lt;/span&gt;&lt;a href="http://subject.it168.com/article/articleview.aspx?id=802107"&gt;&lt;span style="color: #000099;"&gt;Visual Studio 2010对并行计算的支持&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;rdquo;文章中，我们介绍了如何利用Parallel.For和Parallel.ForEach函数来并行化for循环和foreach循环。实际上，Parallel.For和Parallel.ForEach函数主要是针对&amp;ldquo;并行数据&amp;rdquo;的并行化操作，所谓并行数据，就是整个数据集中数据单元是相互独立的，可以同时进行处理。在实际开发中，我们遇到的可以并行处理的不仅包括&amp;ldquo;并行数据&amp;rdquo;，还包括可以同时进行的&amp;ldquo;并行逻辑&amp;rdquo;。所谓&amp;ldquo;并行逻辑&amp;rdquo;，就是相互独立，可以同时执行的多个任务。比如，程序员陈良乔每天早上要做两件事情：烧水洗脸和锻炼身体。这两件事情就是相互独立可以并行的，也就是说他在烧水的时候可以同时锻炼身体。在以前的单核时代，&lt;/span&gt;&lt;a class="nounderline" title="CPU" href="http://product.it168.com/list/b/0217_1.shtml" target="_blank"&gt;CPU&lt;/a&gt;&lt;span&gt;在同一时间只能完成一件事情，那么陈良乔只能先烧水后锻炼，或者是先锻炼后烧水，这导致他上班总是迟到。进入多核时代，CPU可以在同一时间完成多件事情了，借助.Net Framework 4.0中的Parallel类，我们可以方便地处理&amp;ldquo;并行逻辑&amp;rdquo;。现在，程序员陈良乔可以一边锻炼一边烧水，再也没有迟到过了。他逢人便说：&amp;ldquo;Parallel真是个好东西!自从用了它，我腰也不酸了，背也不疼了，编程更有劲儿了。。。&amp;rdquo;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;strong&gt;使用Parallel.Invoke处理并行逻辑&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;strong&gt;&lt;/strong&gt;&lt;span&gt;跟Parallel.For函数相似，Parallel.Invoke也是Parallel类的一个静态函数，它可以接受一个Action[]类型的对象作为参数，这个对象，就是我们要执行的任务。系统会根据代码运行的硬件环境，主要是CPU运算核心的个数，自动地进行线程的创建和分配。这有些类似于我们所熟悉的多线程开发，通过为每个线程指定一个线程函数而让多个任务同时进行，只是Parallel.Invoke函数简化了线程的创建和分配等繁琐的动作，我们只需要提供核心的线程函数就可以了。下面我们来看一个实际的例子。在上文中，我们介绍了程序员陈良乔起床的例子，在以前的单核时代，他起床大约是这个样子的：&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;      &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 串行式起床&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; GetUp()&lt;br /&gt;        {&lt;br /&gt;            Start(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;GetUp&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 先烧水&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            boil();&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 后锻炼&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            exercise();&lt;br /&gt;            End(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;GetUp&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 锻炼&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; exercise()&lt;br /&gt;        {&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Exercise&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            Thread.Sleep(&lt;span style="color: #800080;"&gt;2000&lt;/span&gt;);&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Finish Exercise&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 烧水&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; boil()&lt;br /&gt;        {&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Boil&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            Thread.Sleep(&lt;span style="color: #800080;"&gt;3000&lt;/span&gt;);&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Finish Boil&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;在单核时代，CPU在同一时间只能做一件事情，所以他只能先烧水，后锻炼，这样显然会耽误时间。一天，他又因为这事而迟到了，老板骂道，&amp;ldquo;你是猪啊，你不会用Parallel.Invoke一边烧水一边锻炼啊？&amp;rdquo;于是，有了下面的并行式起床：&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 并行式起床&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ParallelGetUp()&lt;br /&gt;        {&lt;br /&gt;            Start(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ParallelGetUp&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 在烧水的同时，锻炼身体&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; steps = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Action[] { () =&amp;gt; boil(), () =&amp;gt; exercise() };&lt;br /&gt;            Parallel.Invoke(steps);&lt;br /&gt;            End(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ParallelGetUp&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;        }&lt;/div&gt;&lt;p&gt;通过Parallel.Invoke函数，我们将一些相互独立的任务同时执行，实现了&amp;ldquo;并行逻辑&amp;rdquo;，也大大地提高了应用程序的性能和效率。从下面的截图中，我们可以明显地看出两种方式的差别。串行方式所耗费的时间，是两个步骤的时间总和，而并行方式所耗费的时间，大约是单个任务的耗时最长的哪一个。&lt;/p&gt;&lt;p id="img9222521"&gt;&lt;img src="http://image4.it168.com/2010/3/18/001cf7d3-90b1-4374-9c5a-3fb03e15bc53.jpg" alt="" width="535" height="259" /&gt;&lt;/p&gt;&lt;p&gt;图1 串行和并行的执行情况&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span&gt;　&lt;/span&gt;&lt;strong&gt;对Parallel.Invoke进行控制&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;Parallel.Invoke提供了一个重载版本，它可以接受一个ParallelOptions对象作为参数，对Parallel.Invoke的执行进行控制。通过这个对象，我们可以控制并行的最大线程数，各个任务是否取消执行等等。例如，在一个智能化的家中，系统会判断主人是否离开房间，如果主人离开了房间，则自动关闭屋子里的各种电器。利用Parallel.Invoke我们可以实现如下：&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; PInvokeCancel()&lt;br /&gt;{&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建取消对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;CancellationTokenSource cts = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; CancellationTokenSource();&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 利用取消对象，创建ParallelOptions&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;ParallelOptions pOption = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ParallelOptions() { CancellationToken = cts.Token };&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 设置最大线程数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;pOption.MaxDegreeOfParallelism = &lt;span style="color: #800080;"&gt;2&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建一个守护监视进程&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Task.Factory.StartNew(() =&amp;gt;&lt;br /&gt;{&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Cancellation in 5 sec.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;Thread.Sleep(&lt;span style="color: #800080;"&gt;5000&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 取消，结束任务的执行&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;cts.Cancel();&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Canceled requested&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;try&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 以ParallelOptions作为参数，&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 调用Parallel.Invoke&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Parallel.Invoke(pOption, () =&amp;gt; ShutdownLights(pOption.CancellationToken),&lt;br /&gt;() =&amp;gt; ShutdownComputer(pOption.CancellationToken));&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;输出执行结果&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Lights and computer are tuned off.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;catch&lt;/span&gt; (Exception e)&lt;br /&gt;{&lt;br /&gt;Console.WriteLine(e.Message);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ShutdownLights(CancellationToken token)&lt;br /&gt;{&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;while&lt;/span&gt; (!token.IsCancellationRequested)&lt;br /&gt;{&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Light is on. &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; );&lt;br /&gt;Thread.Sleep(&lt;span style="color: #800080;"&gt;1000&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ShutdownComputer(CancellationToken token)&lt;br /&gt;{&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;while&lt;/span&gt; (!token.IsCancellationRequested)&lt;br /&gt;{&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Computer is on.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; );&lt;br /&gt;Thread.Sleep(&lt;span style="color: #800080;"&gt;1000&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;&lt;br /&gt;&lt;span&gt;除了这种方式之外，ParallelOptions更多地应用在取消任务队列中还未来得及执行的任务。当我们限制了最大并发线程数的时候，如果需要通过Parallel.Invoke执行的任务较多，则有可能部分任务在队列中排队而得不到及时的执行，如果到了一定的条件这些任务还没有执行，我们可能取消这些任务。一个恰当的现实生活中的例子就是火车站买票。火车站买票的人很多，但是售票的窗口有限，当到了下班时间后，窗口就不再售票了，也就是剩下的售票任务需要取消掉。我们可以用下面的代码来模拟这样一个场景：&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; PInvokeCancel()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建取消对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;CancellationTokenSource cts = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; CancellationTokenSource();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 利用取消对象，创建ParallelOptions&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;ParallelOptions pOption = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ParallelOptions() { CancellationToken = cts.Token };&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 设置最大线程数，也就相当于20个售票窗口&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;pOption.MaxDegreeOfParallelism = &lt;span style="color: #800080;"&gt;20&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建一个守护监视进程&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 当到下班时间后就取消剩下的售票活动&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Task.Factory.StartNew(() =&amp;gt;&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Cancellation in 5 sec.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;Thread.Sleep(&lt;span style="color: #800080;"&gt;5000&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 取消，结束任务的执行&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;cts.Cancel();&lt;br /&gt;&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Canceled requested&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;try&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建售票活动&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Action[] CustomerServices = CreateCustomerService(&lt;span style="color: #800080;"&gt;1000&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 以ParallelOptions作为参数，&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 调用Parallel.Invoke&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Parallel.Invoke(pOption, CustomerServices);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;catch&lt;/span&gt; (Exception e)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 当任务取消后，抛出一个异常&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Console.WriteLine(e.Message);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建售票的活动&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; Action[] CreateCustomerService(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; n)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;Action[] result = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Action[n];&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = &lt;span style="color: #800080;"&gt;0&lt;/span&gt;; i &amp;lt; n; i++)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;result[i] = () =&amp;gt;&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Customer Service {0}&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, Task.CurrentId);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 模拟售票需要的时间&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Thread.Sleep(&lt;span style="color: #800080;"&gt;2000&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; result;&lt;br /&gt;&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;　&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;strong&gt;并行任务之间的同步&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;有时候我们在处理并行任务的时候，各个任务之间需要同步，也就是同时执行的并行任务，需要在共同到达某一个状态的后再一共继续执行。我们可以举一个现实生活中的例子。陈良乔，贾玮和单春晖是好朋友，他们相约到电影院看《建国大业》。他们三个住在不同的地方，为了能一起买票进电影院，他们约好先在电影院门口的KFC会合，然后再一起进电影院。这其中就涉及到一个同步的问题：他们需要先在KFC会合。他们是从家里分别到KFC的，但是需要在KFC进行同步，等到三个人都到齐后在完成后后继的动作，进电影院看电影。&lt;/p&gt;&lt;p&gt;为了完成并行任务之间的同步，.NET Framework中提供了一个类Barrier。顾名思义，Barrier就像一个关卡或者是剪票口一样，通过Barrier类，我们可以管理并行任务的执行，完成他们之间的同步。Barrier类的使用非常简单，我们只需要在主线程中声明一个Barrier对象，同时指明需要同步的任务数。然后，在需要进行同步的地方调用Barrier类的SignalAndWait函数就可以了。 当一个并行任务到达SignalAndWait后，它会暂停执行，等待所有并行任务都到达同步点之后再继续往下执行。下面我们以一个实际的例子，来看看如何利用Barrier类完成看电影的同步问题。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Linq;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Threading;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Threading.Tasks;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt; ParallelBarrier&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 用于同步的Barrier对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; Barrier sync;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建Barrier对象，这里我们需要同步&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 任务有三个&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;sync = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Barrier(&lt;span style="color: #800080;"&gt;3&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 开始执行并行任务&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; steps = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Action[] { () =&amp;gt; gotothecinema(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;陈良乔&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, TimeSpan.FromSeconds(&lt;span style="color: #800080;"&gt;5&lt;/span&gt;) ),&lt;br /&gt;&lt;br /&gt;() =&amp;gt; gotothecinema(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;贾玮&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, TimeSpan.FromSeconds(&lt;span style="color: #800080;"&gt;2&lt;/span&gt;) ),&lt;br /&gt;&lt;br /&gt;() =&amp;gt; gotothecinema(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;单春晖&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, TimeSpan.FromSeconds(&lt;span style="color: #800080;"&gt;4&lt;/span&gt;) )};&lt;br /&gt;&lt;br /&gt;Parallel.Invoke(steps);&lt;br /&gt;&lt;br /&gt;Console.ReadKey();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 任务&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; gotothecinema(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; strName, TimeSpan timeToKFC )&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;[{0}] 从家里出发。&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, strName);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 从家里到KFC&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Thread.Sleep(timeToKFC);&lt;br /&gt;&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;[{0}] 到达KFC。&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, strName);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 等待其他人到达&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;sync.SignalAndWait();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 同步后，进行后继动作&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;[{0}] 买票进电影院。&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, strName);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在这段代码中，我们首先创建了Barrier对象，因为在这里需要同步的任务有三个，所以创建Barrier对象时是的参数是3。然后就是使用Parallel.Invoke执行并行任务。我们在并行任务gotothecinema中设置了一个同步点，在这里我们调用Barrier对象的SignalAndWait函数，它表示当前任务已经到达同步点并同时等待其他任务到达同步点。当所有任务都到达同步点之后，再继续往下执行。运行上面的程序，我们可以获得这样的输出：&lt;/p&gt;&lt;p id="img7792193"&gt;&lt;img src="http://image4.it168.com/2010/3/18/a23ad709-f673-45ea-9900-a8bcd0403f13.jpg" alt="" width="342" height="226" /&gt;&lt;/p&gt;&lt;p&gt;图2 使用Barrier进行同步&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;更复杂的任务之间的同步&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们在使用Barrier进行并行任务之间的同步时，有这样一个缺陷，我们需要预先知道所有需要同步的并行任务的数目，如果这个数目是随机的，就无法使用Barrier进行任务之间的同步了。并行任务数目不定这种情况很常见。我们还是来看上文中看电影的例子，每场进电影院看电影的观众数目是不固定的，那么退场的观众也是不固定的，甚至还有中途退场的。当所有观众都退场后，我们需要打扫电影院的卫生。这里需要的同步的就是所有观众都退场。针对这种数目不定的多个并行任务，.NET Framework提供了CountdownEvent这个类来进行任务之间的同步。&lt;/p&gt;&lt;p&gt;就像它的名字一样，CountdownEvent基于这样一个简单的规则：当有新的需要同步的任务产生时，就调用AddCount增加它的计数，当有任务到达同步点是，就调用Signal函数减小它的计数，当CountdownEvent的计数为零时，就表示所有需要同步的任务已经完成，可以开始下一步任务了。下面我们利用CountdownEvent来模拟一下观众进场立场的情景。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt; &lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Linq;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Threading;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Threading.Tasks;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt; CountdownEventDemo&lt;br /&gt; &lt;br /&gt; {&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 观众类，用来表示一位观众&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Customer&lt;br /&gt; &lt;br /&gt; {&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; Customer(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; nID)&lt;br /&gt; &lt;br /&gt; {&lt;br /&gt; &lt;br /&gt; m_nID = nID;&lt;br /&gt; &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 观众的ID&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; m_nID;&lt;br /&gt; &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt; &lt;br /&gt; {&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt; &lt;br /&gt; {&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建CountdownEvent同步对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; countdown = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; CountdownEvent(&lt;span style="color: #800080;"&gt;1&lt;/span&gt;))&lt;br /&gt; &lt;br /&gt; {&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 产生一个随机数，表示观众的数目&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; Random countRandom = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Random(DateTime.Now.Millisecond);&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; nCount = countRandom.Next(&lt;span style="color: #800080;"&gt;10&lt;/span&gt;);&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 构造每一位观众看电影的任务&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; Action[] seeafilm = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Action[ nCount ];&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = &lt;span style="color: #800080;"&gt;0&lt;/span&gt;; i &amp;lt; nCount; i++)&lt;br /&gt; &lt;br /&gt; {&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 构造Customer对象，表示观众&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; Customer currentCustomer = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Customer( i+&lt;span style="color: #800080;"&gt;1&lt;/span&gt; );&lt;br /&gt; &lt;br /&gt; seeafilm[i] = () =&amp;gt;&lt;br /&gt; &lt;br /&gt; {&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 观众进场&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; countdown.AddCount();&lt;br /&gt; &lt;br /&gt; Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;观众 {0} 进场。&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, currentCustomer.m_nID);&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 模拟看电影的时间&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; Thread.Sleep(countRandom.Next(&lt;span style="color: #800080;"&gt;3000&lt;/span&gt;,&lt;span style="color: #800080;"&gt;6000&lt;/span&gt;));&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 观众退场&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; countdown.Signal();&lt;br /&gt; &lt;br /&gt; Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;观众 {0} 退场。&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, currentCustomer.m_nID);&lt;br /&gt; &lt;br /&gt; };&lt;br /&gt; &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;并行执行任务&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; Parallel.Invoke( seeafilm );&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 在此同步，最后CountdownEvent的计数变为零&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;br /&gt; countdown.Signal();&lt;br /&gt;&lt;br /&gt;countdown.Wait();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;所有观众退场，开始打扫卫生。&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;Console.ReadKey();&lt;br /&gt;&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;在这段代码中，我们使用CountdownEvent进行随机个数任务之间的同步。最后，我们可以得到这样的输出。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p id="img5650679"&gt;&lt;img src="http://image4.it168.com/2010/3/18/a408eb7f-3e22-4e0b-8068-fd66bec0a4be.jpg" alt="" width="539" height="213" /&gt;&lt;/p&gt;&lt;p&gt;图3 使用CountdownEvent进行同步&lt;/p&gt;&lt;p&gt;通过Parallel.Invoke函数，我们可以轻松地将相互独立的任务并行执行，同时通过Barrier和CountdownEvent类进行任务之间的同步。这种并行计算的开发方式，比以前那种基于线程的并行计算开发方式简便很多，解放了程序员的脑袋，让他们可以把更多的脑力放到业务逻辑问题的解决之上。&lt;/p&gt;&lt;p&gt;使用Parallel类，多快好省地开发并行计算应用程序。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/asyuras/aggbug/2411513.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/asyuras/archive/2012/03/22/2411513.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/asyuras/archive/2011/12/21/2296118.html</id><title type="text">文件格式相关开源项目</title><summary type="text">NPOI语言: C#官方网站:http://npoi.codeplex.com/描述: NPOI是POI的.NET移植版本，目前稳定版本中仅支持对xls文件（Excel 97-2003）文件格式的读写。目前的NPOI版本主要是基于POI 3.2的，目前正在将部分POI 3.5的bug修整放入新版本中。相关文件格式: xls, OLE2格式工具：POIFS Browser代码协议： Apache 2.0Office Binary Translator to Open XML语言： c#官方网站:http://b2xtranslator.sourceforge.net/描述: 这个项目的主要目的是</summary><published>2011-12-21T09:41:00Z</published><updated>2011-12-21T09:41:00Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><link rel="alternate" href="http://www.cnblogs.com/asyuras/archive/2011/12/21/2296118.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/archive/2011/12/21/2296118.html"/><content type="html">&lt;p&gt;&lt;strong&gt;NPOI&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言: C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://npoi.codeplex.com/"&gt;http://npoi.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: NPOI是POI的.NET移植版本，目前稳定版本中仅支持对xls文件（Excel 97-2003）文件格式的读写。目前的NPOI版本主要是基于POI 3.2的，目前正在将部分POI 3.5的bug修整放入新版本中。&lt;/p&gt;&lt;p&gt;相关文件格式: xls, OLE2格式&lt;/p&gt;&lt;p&gt;工具：POIFS Browser&lt;/p&gt;&lt;p&gt;代码协议： Apache 2.0&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Office Binary Translator to Open XML&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言： c#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://b2xtranslator.sourceforge.net/"&gt;http://b2xtranslator.sourceforge.net/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: 这个项目的主要目的是把Office 97-2003的文件格式转换成Open XML格式，为其他软件提供参考。&lt;/p&gt;&lt;p&gt;相关工具: BiffView++ (下载&lt;a href="http://b2xtranslator.sourceforge.net/snapshots/BiffView.zip"&gt;zip&lt;/a&gt;文件)&lt;/p&gt;&lt;p&gt;相关文件格式：doc/docx, ppt/pptx, xls/xlsx&lt;/p&gt;&lt;p&gt;代码协议：BSD&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Open XML Format SDK&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;官方网站：&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c6e744e5-36e9-45f5-8d8c-331df206e0d0&amp;amp;DisplayLang=en"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=c6e744e5-36e9-45f5-8d8c-331df206e0d0&amp;amp;DisplayLang=en&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述：微软官方提供的Open XML读写库，目前最新版是2.0 CTP版本。&lt;/p&gt;&lt;p&gt;相关文件格式：Open XML Formats (docx, xlsx, pptx等)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;ZeraldotNet&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言： c#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://www.codeplex.com/ZeraldotNet"&gt;http://www.codeplex.com/ZeraldotNet&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: Zeral .Net类库实现了BitTorrent协议、eMule协议、Overnet协议和Gnutella协议。&lt;/p&gt;&lt;p&gt;相关文件格式： .torrent&lt;/p&gt;&lt;p&gt;代码协议：Ms-CL v1.1&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;NAudio&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言: C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://www.codeplex.com/naudio"&gt;http://www.codeplex.com/naudio&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: NAudio是一套实用的音频类库，目的是加快.NET上音频相关工具的开发。它诞生于2001年，现在已经有了很多功能。&lt;/p&gt;&lt;p&gt;相关文件格式: MP3, OGG, SFZ, MIDI, SoundFont, WAV&lt;/p&gt;&lt;p&gt;代码协议：Ms-PL&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;DotNetZip&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言: C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://www.codeplex.com/DotNetZip"&gt;http://www.codeplex.com/DotNetZip&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: DotNetZip是一个小巧、使用简便的zip类库。用VB.NET及C#写的应用程序都能简单方便的创建、阅读和更新zip文件。&lt;/p&gt;&lt;p&gt;相关文件格式: zip&lt;/p&gt;&lt;p&gt;代码协议：Ms-PL&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;7zSharp&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言: C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://www.codeplex.com/7zsharp"&gt;http://www.codeplex.com/7zsharp&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: 7zSharp是基于.NET 2.0的7z LZMA二次开发包，提供了一套便捷的API用于解密和加密7z文件。&lt;/p&gt;&lt;p&gt;相关文件格式: 7z (.7z), ZIP (.zip), GZIP (.gz), BZIP2 (.bz2) and TAR (.tar), RAR (.rar), CAB (.cab), ISO (.iso), ARJ (.arj), LZH (.lzh), CHM (.chm), Z (.Z), CPIO (.cpio), RPM (.rpm), DEB (.deb), NSIS (.nsis)&lt;/p&gt;&lt;p&gt;代码协议：LGPL 2.1&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;iTextSharp&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言: C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://sourceforge.net/projects/itextsharp/"&gt;http://sourceforge.net/projects/itextsharp/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: iText# (iTextSharp)是iText Java开源库的C#移植版本，它可以让你从头开始生成PDF。&lt;/p&gt;&lt;p&gt;相关文件格式: PDF, rtf, bmp, gif, png,tiff, jpeg&lt;/p&gt;&lt;p&gt;相关技术: OpenPGP, OpenSSL, TSP(时间戳协议), x509, ocsp, BigInterger, BCPG&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;GifLib&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言: C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://www.codeplex.com/GifLib"&gt;http://www.codeplex.com/GifLib&lt;/a&gt;或&lt;a href="http://www.cndotnet.org/GifLib"&gt;http://www.cndotnet.org/GifLib&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: GifLib能够无损读写Gif格式&lt;/p&gt;&lt;p&gt;相关文件格式: gif&lt;/p&gt;&lt;p&gt;相关技术: LZW压缩&lt;/p&gt;&lt;p&gt;代码协议：BSD&lt;/p&gt;&lt;p&gt;&lt;strong&gt;.NET DiscUtil&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言：C#&lt;/p&gt;&lt;p&gt;官方网站：&lt;a href="http://discutils.codeplex.com/"&gt;http://discutils.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;相关文件格式：ISO, FAT, NTFS, VHD, XVA, VMDK和VDI&lt;/p&gt;&lt;p&gt;描述：可读写ISO文件和虚拟机磁盘文件格式（VHD, VDI, XVA, VMDK等）的库，完全用C#实现，没有P-Invoke。&lt;/p&gt;&lt;p&gt;代码协议：MIT&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UOF and OOXML translator&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;官方网站：&lt;a href="http://uof-translator.sourceforge.net/"&gt;http://uof-translator.sourceforge.net/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;相关文件格式：UOF, Open XML Formats&lt;/p&gt;&lt;p&gt;描述：这是微软公司、北京大学、LiSoft、清华大学、北京科技大学共同开发的开源项目，目的是实现UOF和OOXML的双向转换。目前最新版本是2.0，貌似正在开发2.1版本。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;JPEG Data&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;环境：.NET 3.5 sp1&lt;/p&gt;&lt;p&gt;官方网站：&lt;a href="http://jpegdata.codeplex.com/"&gt;http://jpegdata.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;相关文件格式：jpeg&lt;/p&gt;&lt;p&gt;描述：从jpeg中获得需要的数据&lt;/p&gt;&lt;p&gt;代码协议：Ms-PL&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Mp4 Explorer&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;官方网站：&lt;a href="http://mp4explorer.codeplex.com/"&gt;http://mp4explorer.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;相关文件格式：mp4格式&lt;/p&gt;&lt;p&gt;描述：可用于从MPEG-4 iso文件（(ISO/IEC 14496-12, ISO/IEC 14496-14, ISO/IEC 14496-15)）中读取各种信息，如mp4头，元数据和其他数据&lt;/p&gt;&lt;p&gt;代码协议：Ms-PL&lt;/p&gt;&lt;p&gt;&lt;strong&gt;NetCDF Library for .NET&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言: J#, C# wrapper&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://netcdf.codeplex.com/"&gt;http://netcdf.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: 这个项目从Java版本的NETCDF Library移植过来的，Java版的库是ESSE项目（环境场景搜索引擎）的一部分，这个项目由地球物理学中心俄罗斯研究中心、国家地球物理学数据中心NOAA、微软研究院以及剑桥参与完成&lt;/p&gt;&lt;p&gt;相关文件格式: netcdf&lt;/p&gt;&lt;p&gt;代码协议： GPL 2.1&lt;/p&gt;&lt;p&gt;&lt;strong&gt;WBFS Manager&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言：C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://wbfsmanager.codeplex.com/"&gt;http://wbfsmanager.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: WII游戏机必备的硬盘管理工具。&lt;/p&gt;&lt;p&gt;相关研究领域: WBFS （WII文件系统格式，类似FAT）&lt;/p&gt;&lt;p&gt;代码协议： GPLv2&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Duplicate images finder&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言：C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://duplifinder.codeplex.com/"&gt;http://duplifinder.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: 这是一个能够帮你找到相似照片的应用，注意是相似，不是相同。&lt;/p&gt;&lt;p&gt;相关研究领域: jpeg格式、图像处理、相似度比较&lt;/p&gt;&lt;p&gt;代码协议： Ms-PL&lt;/p&gt;&lt;p&gt;&lt;strong&gt;#SNMP&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言：C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://sharpsnmplib.codeplex.com/"&gt;http://sharpsnmplib.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: SNMP协议的.NET实现&lt;/p&gt;&lt;p&gt;相关文件格式: snmp&lt;/p&gt;&lt;p&gt;代码协议： GPL 2.1&lt;/p&gt;&lt;p&gt;&lt;strong&gt;zxing&lt;/strong&gt;&amp;nbsp;(Zebra Crossing)&lt;/p&gt;&lt;p&gt;语言：java （同时提供C#, C++, Ruby, actionscript的封装）&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://code.google.com/p/zxing/"&gt;http://code.google.com/p/zxing/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: 非常专业的1D/2D条形码生成类库，同时支持PC和手机应用，能够在iphone、andriod、rim等系统上使用&lt;/p&gt;&lt;p&gt;相关研究领域: 图像处理，条形码，UPC, Code 39,93,128,QR code, ITF&lt;/p&gt;&lt;p&gt;&lt;strong&gt;.NET DiscUtils&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言：C#&lt;/p&gt;&lt;p&gt;官方网站：&lt;a href="http://discutils.codeplex.com/"&gt;http://discutils.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: 纯.NET实现的磁盘文件读写库，支持各种虚拟机硬盘文件和ISO文件格式，支持刻录&lt;/p&gt;&lt;p&gt;相关研究领域: 虚拟机磁盘文件（VHD, VDI, XVA, VMDK）, ISO, UDF, FAT, NTFS,&lt;/p&gt;&lt;p&gt;代码协议： MIT&lt;/p&gt;&lt;p&gt;&lt;strong&gt;GomuIso9660&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言：C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://gomuiso9660.codeplex.com/"&gt;http://gomuiso9660.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: 可用于读取各种光盘文件格式，支持刻录。&lt;/p&gt;&lt;p&gt;相关研究领域: iso, bin, mdf, nrg, img, cdi，光盘刻录&lt;/p&gt;&lt;p&gt;代码协议： Ms-PL&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Website Screenshots &amp;amp; Thumbnails Extractor&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言：C#&lt;/p&gt;&lt;p&gt;官方网站:&amp;nbsp;&lt;a href="http://screenshotsextractor.codeplex.com/"&gt;http://screenshotsextractor.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述: 网站截图工具，能够实现整页滚动截取，类似Fireshot&lt;/p&gt;&lt;p&gt;相关研究领域: 网页截图、屏幕截图&lt;/p&gt;&lt;p&gt;代码协议： Ms-PL&lt;/p&gt;&lt;p&gt;&lt;strong&gt;HtmlAgility&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;语言：C#&lt;/p&gt;&lt;p&gt;官方网站：&lt;a href="http://htmlagilitypack.codeplex.com/"&gt;http://htmlagilitypack.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;描述：可解析HTML的DOM结构，不依赖任何第三方组件，纯.NET实现&lt;/p&gt;&lt;p&gt;相关研究领域：HTML, XHTML&lt;/p&gt;&lt;p&gt;代码协议：Ms-PL&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;转自：&lt;a href="http://tonyqus.sinaapp.com/archives/40"&gt;http://tonyqus.sinaapp.com/archives/40&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/asyuras/aggbug/2296118.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/asyuras/archive/2011/12/21/2296118.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/asyuras/archive/2011/06/17/2083805.html</id><title type="text">利用DataAnnotations验证实体(类)的属性</title><summary type="text">.NET 4 和Silverlight 中可以使用以下方法:public static void Validate(this Entity entity){ // prepare the result var validationResults = new List&lt;ValidationResult&gt;(); // create a validation context var validationContext = new ValidationContext(entity, null, null); // validate Validator.TryValidateObject(e</summary><published>2011-06-17T09:02:00Z</published><updated>2011-06-17T09:02:00Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><link rel="alternate" href="http://www.cnblogs.com/asyuras/archive/2011/06/17/2083805.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/archive/2011/06/17/2083805.html"/><content type="html">&lt;p&gt;.NET 4 和Silverlight 中可以使用以下方法:&lt;/p&gt;&lt;p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public static void Validate(this Entity entity)&lt;br/&gt;{&lt;br/&gt;    // prepare the result&lt;br/&gt;    var validationResults = new List&amp;lt;ValidationResult&amp;gt;();&lt;br/&gt;    // create a validation context&lt;br/&gt;    var validationContext = new ValidationContext(entity, null, null);&lt;br/&gt;    // validate&lt;br/&gt;    Validator.TryValidateObject(entity, validationContext, validationResults);&lt;br/&gt;    // reset the validation errors of the entity&lt;br/&gt;    entity.ValidationErrors.Clear();&lt;br/&gt;    foreach (var error in validationResults)&lt;br/&gt;        entity.ValidationErrors.Add(error);&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;.NET 3.5中的方法：&lt;/p&gt;&lt;p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public static class EntityValidator&lt;br/&gt;{&lt;br/&gt;public static IEnumerable&amp;lt;ErrorField&amp;gt; GetErrors(object instance)&lt;br/&gt;{&lt;br/&gt;var t = instance.GetType();&lt;br/&gt;var typeDescriptor = new AssociatedMetadataTypeTypeDescriptionProvider(t).GetTypeDescriptor(t);&lt;br/&gt;&lt;br/&gt;return from prop in typeDescriptor.GetProperties().Cast&amp;lt;PropertyDescriptor&amp;gt;()&lt;br/&gt; from attribute in prop.Attributes.OfType&amp;lt;ValidationAttribute&amp;gt;()&lt;br/&gt; where !attribute.IsValid(prop.GetValue(instance))&lt;br/&gt; select new ErrorField(prop.Name, attribute.FormatErrorMessage(string.Empty));&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;[Serializable]&lt;br/&gt;public class ErrorField&lt;br/&gt;{&lt;br/&gt;public string ID { get; set; }&lt;br/&gt;&lt;br/&gt;public string Msg { get; set; }&lt;br/&gt;&lt;br/&gt;public ErrorField(string id, string msg)&lt;br/&gt;{&lt;br/&gt;this.ID = id;&lt;br/&gt;this.Msg = msg;&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/asyuras/aggbug/2083805.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/asyuras/archive/2011/06/17/2083805.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/asyuras/archive/2011/02/01/1948547.html</id><title type="text">复制一个List&amp;lt;T&amp;gt;对象</title><summary type="text">对于值类型的List直接用以下方法就可以复制：对于引用类型的List无法用以上方法进行复制，只会复制List中对象的引用，可以用以下扩展方法复制：当然前题是List中的对象要实现ICloneable接口另一个更保险的方法是：</summary><published>2011-02-01T01:43:00Z</published><updated>2011-02-01T01:43:00Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><link rel="alternate" href="http://www.cnblogs.com/asyuras/archive/2011/02/01/1948547.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/archive/2011/02/01/1948547.html"/><content type="html">&lt;p&gt;对于值类型的List直接用以下方法就可以复制：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;List&amp;lt;T&amp;gt; oldList = new List&amp;lt;T&amp;gt;();&lt;br/&gt;oldList.Add(..);&lt;br/&gt;List&amp;lt;T&amp;gt; newList = new List&amp;lt;T&amp;gt;(oldList);&lt;br/&gt;&lt;/div&gt;&lt;p&gt;对于引用类型的List无法用以上方法进行复制，只会复制List中对象的引用，可以用以下扩展方法复制：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;static class Extensions&lt;br/&gt;{&lt;br/&gt;        public static IList&amp;lt;T&amp;gt; Clone&amp;lt;T&amp;gt;(this IList&amp;lt;T&amp;gt; listToClone) where T: ICloneable&lt;br/&gt;        {&lt;br/&gt;                return listToClone.Select(item =&amp;gt; (T)item.Clone()).ToList();&lt;br/&gt;        }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;当然前题是List中的对象要实现ICloneable接口&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;另一个更保险的方法是：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public static T Clone&amp;lt;T&amp;gt;(T RealObject)&lt;br/&gt;{&lt;br/&gt;    using (Stream objectStream = new MemoryStream())&lt;br/&gt;    {&lt;br/&gt;            IFormatter formatter = new BinaryFormatter();&lt;br/&gt;            formatter.Serialize(objectStream, RealObject);&lt;br/&gt;            objectStream.Seek(0, SeekOrigin.Begin);&lt;br/&gt;            return (T)formatter.Deserialize(objectStream);&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/asyuras/aggbug/1948547.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/asyuras/archive/2011/02/01/1948547.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/asyuras/archive/2010/12/13/1904283.html</id><title type="text">删除所有符合的目录包括子目录</title><summary type="text">for /d /r . %d in (.svn) do @if exist "%d" rd /s/q "%d"</summary><published>2010-12-13T03:33:00Z</published><updated>2010-12-13T03:33:00Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><link rel="alternate" href="http://www.cnblogs.com/asyuras/archive/2010/12/13/1904283.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/archive/2010/12/13/1904283.html"/><content type="html">&lt;p&gt;for /d /r . %d in (.svn) do @if exist "%d" rd /s/q "%d"&lt;/p&gt;&lt;img src="http://www.cnblogs.com/asyuras/aggbug/1904283.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/asyuras/archive/2010/12/13/1904283.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/asyuras/archive/2010/09/07/1820349.html</id><title type="text">CKeditor与Asp.net验证控件的问题</title><summary type="text">在Asp.net中，如果给CKeditor加了RequiredField Validator 验证控件，在提交表单时，可能要点两次，点第一次时会出现验证失败，点第二次就可以提交。原因是，点第一次时CKeditor中的内容还未负给Textarea控件。解决方法：</summary><published>2010-09-07T02:30:00Z</published><updated>2010-09-07T02:30:00Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><link rel="alternate" href="http://www.cnblogs.com/asyuras/archive/2010/09/07/1820349.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/archive/2010/09/07/1820349.html"/><content type="html">&lt;p&gt;在Asp.net中，如果给CKeditor加了RequiredField Validator 验证控件，在提交表单时，可能要点两次，点第一次时会出现验证失败，点第二次就可以提交。原因是，点第一次时CKeditor中的内容还未负给Textarea控件。解决方法：&lt;/p&gt;&lt;p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&amp;lt;script src="_scripts/jquery-1.3.2.min.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;&lt;br/&gt;    &amp;lt;script type="text/javascript" src="ckeditor/ckeditor.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br/&gt;    &amp;lt;script type="text/javascript" src="ckeditor/adapters/jquery.js"&amp;gt;&amp;lt;/script&amp;gt; &lt;br/&gt;    &amp;lt;script type="text/javascript" language="javascript"&amp;gt;&lt;br/&gt;        $(document).ready(function() {&lt;br/&gt;            $('#TextBox1').ckeditor();&lt;br/&gt;        });&lt;br/&gt;       &lt;br/&gt;        function UpdateContent() {          &lt;br/&gt;            var ckeditorinstance = $('#TextBox1').ckeditorGet();&lt;br/&gt;            ckeditorinstance.updateElement();&lt;br/&gt;        }&lt;br/&gt;    &amp;lt;/script&amp;gt;&lt;br/&gt;&amp;lt;/head&amp;gt;&lt;br/&gt;&amp;lt;body&amp;gt;&lt;br/&gt;    &amp;lt;form id="form1" runat="server"&amp;gt;&lt;br/&gt;    &amp;lt;div&amp;gt;&lt;br/&gt;        &amp;lt;asp:TextBox ID="TextBox1" TextMode="MultiLine" runat="server"&amp;gt;&amp;lt;/asp:TextBox&amp;gt; &lt;br/&gt;         &amp;lt;asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"&lt;br/&gt;        ControlToValidate="TextBox1" ErrorMessage="No content in CKEditor!"&amp;gt;&amp;lt;/asp:RequiredFieldValidator&amp;gt; &lt;br/&gt;    &amp;lt;/div&amp;gt;&lt;br/&gt;    &amp;lt;asp:Button ID="btnSave" OnClientClick="javascript:UpdateContent()" runat="server" Text="Save" onclick="btnSave_Click" /&amp;gt;&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/asyuras/aggbug/1820349.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/asyuras/archive/2010/09/07/1820349.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/asyuras/archive/2010/08/26/1808912.html</id><title type="text">清空SqlServer中所有表的数据</title><summary type="text">sp_MSforeachtable @command1='Delete from ?'sp_MSforeachtable使用方法1)说明系统存储过程sp_MSforeachtable和sp_MSforeachdb,是微软提供的两个不公开的存储过程,从ms sql 6.5开始。存放在SQL Server的MASTER数据库中。2)参数说明:@command1 nvarchar(2000), --第一...</summary><published>2010-08-26T03:32:00Z</published><updated>2010-08-26T03:32:00Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><link rel="alternate" href="http://www.cnblogs.com/asyuras/archive/2010/08/26/1808912.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/archive/2010/08/26/1808912.html"/><content type="html">&lt;p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;sp_MSforeachtable @command1='Delete from ?'&lt;br/&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;sp_MSforeachtable使用方法&lt;br/&gt;&lt;br/&gt;1)说明&lt;br/&gt;系统存储过程sp_MSforeachtable和sp_MSforeachdb,是微软提供的两个不公开的存储过程,从ms sql 6.5开始。&lt;br/&gt;存放在SQL Server的MASTER数据库中。&lt;br/&gt;&lt;br/&gt;2)参数说明:&lt;br/&gt;@command1 nvarchar(2000),          --第一条运行的SQL指令&lt;br/&gt;@replacechar nchar(1) = N'?',      --指定的占位符号&lt;br/&gt;@command2 nvarchar(2000)= null,    --第二条运行的SQL指令&lt;br/&gt;@command3 nvarchar(2000)= null,    --第三条运行的SQL指令&lt;br/&gt;@whereand nvarchar(2000)= null,    --可选条件来选择表&lt;br/&gt;@precommand nvarchar(2000)= null,  --执行指令前的操作(类似控件的触发前的操作)&lt;br/&gt;@postcommand nvarchar(2000)= null  --执行指令后的操作(类似控件的触发后的操作)&lt;br/&gt;&lt;br/&gt;3)举例&lt;br/&gt;--统计数据库里每个表的详细情况&lt;br/&gt;exec sp_MSforeachtable @command1="sp_spaceused '?'"&lt;br/&gt;--获得每个表的记录数和容量:&lt;br/&gt;EXEC sp_MSforeachtable @command1="print '?'",&lt;br/&gt;@command2="sp_spaceused '?'",&lt;br/&gt;@command3= "SELECT count(*) FROM ? "&lt;br/&gt;--获得所有的数据库的存储空间:&lt;br/&gt;EXEC sp_MSforeachdb   @command1="print '?'",&lt;br/&gt;@command2="sp_spaceused "&lt;br/&gt;--检查所有的数据库&lt;br/&gt;EXEC sp_MSforeachdb   @command1="print '?'",&lt;br/&gt;@command2="DBCC CHECKDB (?) "&lt;br/&gt;--更新PUBS数据库中已t开头的所有表的统计:&lt;br/&gt;EXEC sp_MSforeachtable @whereand="and name like 't%'",&lt;br/&gt;@replacechar='*',&lt;br/&gt;@precommand="print 'Updating Statistics.....' print ''",&lt;br/&gt;@command1="print '*' update statistics * ",&lt;br/&gt;@postcommand= "print''print 'Complete Update Statistics!'"&lt;br/&gt;--删除当前数据库所有表中的数据&lt;br/&gt;sp_MSforeachtable @command1='Delete from ?'&lt;br/&gt;sp_MSforeachtable @command1 = "TRUNCATE TABLE ?"&lt;br/&gt;&lt;br/&gt;4)参数@whereand的用法&lt;br/&gt;@whereand参数在存储过程中起到指令条件限制的作用,具体的写法如下:&lt;br/&gt;@whereend,可以这么写 @whereand=' AND o.name in (''Table1'',''Table2'',.......)'&lt;br/&gt;例如:我想更新Table1/Table2/Table3中NOTE列为NULL的值&lt;br/&gt;sp_MSforeachtable @command1='Update ? Set NOTE='''' Where NOTE is NULL',@whereand=' AND o.name in (''Table1'',''Table2'',''Table3'')'&lt;br/&gt;&lt;br/&gt;5)"?"在存储过程的特殊用法,造就了这两个功能强大的存储过程&lt;br/&gt;这里"?"的作用,相当于DOS命令中、以及我们在WINDOWS下搜索文件时的通配符的作用。&lt;br/&gt;&lt;/div&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/asyuras/aggbug/1808912.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/asyuras/archive/2010/08/26/1808912.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/asyuras/archive/2010/07/11/1775152.html</id><title type="text">IE,Firefox,Chrome都可用的阴影效果</title><summary type="text">前面两行是FF,Chrome用的，后面是IE专用[代码]</summary><published>2010-07-11T03:46:00Z</published><updated>2010-07-11T03:46:00Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><link rel="alternate" href="http://www.cnblogs.com/asyuras/archive/2010/07/11/1775152.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/archive/2010/07/11/1775152.html"/><content type="html">&lt;p&gt;前面两行是FF,Chrome用的，后面是IE专用&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #800000;"&gt;-webkit-box-shadow:2px 2px 2px #CCC;&lt;br /&gt;&lt;br /&gt;-moz-box-shadow:2px 2px 2px #CCC; &lt;br /&gt;&lt;br /&gt;filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='#CCCCCC', Positive='true')&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/asyuras/aggbug/1775152.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/asyuras/archive/2010/07/11/1775152.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/asyuras/archive/2009/07/15/1523984.html</id><title type="text">CSS Frameworks Collection(css框架收集)</title><summary type="text">什么是css框架事实上让我们开始于什么是框架？框架就是一个你可以用于你的网站项目的基本的概念上的结构体。css框架通常只是一些css文件的集合，这些文件包括基本布局、表单样式、网格或简单结构、以及样式重置。比如：typography.css基本排版规则grid.css基于网格的布局layout.css通常的布局form.cssfor 表单样式general.css更多通用规则不同的css框架Ele...</summary><published>2009-07-15T03:47:00Z</published><updated>2009-07-15T03:47:00Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><link rel="alternate" href="http://www.cnblogs.com/asyuras/archive/2009/07/15/1523984.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/archive/2009/07/15/1523984.html"/><content type="text">什么是css框架事实上让我们开始于什么是框架？框架就是一个你可以用于你的网站项目的基本的概念上的结构体。css框架通常只是一些css文件的集合，这些文件包括基本布局、表单样式、网格或简单结构、以及样式重置。比如：typography.css基本排版规则grid.css基于网格的布局layout.css通常的布局form.cssfor 表单样式general.css更多通用规则不同的css框架Ele...</content></entry><entry><id>http://www.cnblogs.com/asyuras/archive/2009/06/06/1497730.html</id><title type="text">CSS在IE6, IE7, IE8, Firefox中的特定使用(Hack)</title><summary type="text">不同的浏览器对CSS的解释都有一点出入，特别是padding, line-height这些要细微控制的地方，下面的hack基本可以解决这个问题：在属性前加下划线(_)，那么此属性只会被IE6解释在属性前加星号(*)，此属性只会被IE7解释在属性值后面加"\9"，表示此属性只会被IE8解释例如：[代码]</summary><published>2009-06-06T09:42:00Z</published><updated>2009-06-06T09:42:00Z</updated><author><name>大洋</name><uri>http://www.cnblogs.com/asyuras/</uri></author><link rel="alternate" href="http://www.cnblogs.com/asyuras/archive/2009/06/06/1497730.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/asyuras/archive/2009/06/06/1497730.html"/><content type="text">不同的浏览器对CSS的解释都有一点出入，特别是padding, line-height这些要细微控制的地方，下面的hack基本可以解决这个问题：在属性前加下划线(_)，那么此属性只会被IE6解释在属性前加星号(*)，此属性只会被IE7解释在属性值后面加"\9"，表示此属性只会被IE8解释例如：[代码]</content></entry></feed>
