Parallel线程使用
Parallel的静态For,ForEach和Invoke方法
// 一个线程顺序执行这个工作(每次迭代调用一次DoWork)
for (Int32 i = 0; i< 1000; i++ ) DoWork(i);
相反,可以使用Parallel类型的For方法,让多个线程池治线程帮助执行这个工作:
// 线程池的线程并行处理工作
Parallel.For(0,1000,i=>DoWork(i));
类似的,如果有一个集合,那么不要像下面这样写:
// 一个线程顺序执行这个工作(每次迭代调用一次DoWork)
foreach ( var item in conllection) DoWork(item);
而是这样做:
// 线程池的线程并行处理工作
Parallel.ForEach(conllection,item=>DoWork(item));
如果代码中既可以用For,也可以用ForEach,那么建议使用For,因为它执行的快一点。最后,如果要执行几个方法,那么可以顺序执行它们,如下所示:
// 一个线程顺序执行所有方法
Method1();
Method2();
Method3();
也可以并行执行它们:

// 线程池的线程并行执行
parallel.Invoke(
() => Method1(),
() => Method2(),
() => Method3());

Parallel的所有方法都让调用线程参与处理。从资源利用的角度说,这是一件好事,因为我们不希望调用线程停下来,等待线程池做完所有工作后才继续。然而,如果调用线程在线程池完成自己的那一部分工作之前完成工作,调用程序就会将自己挂起,知道所有工作完成。这也是一件好事,因为这个提供了和普通for和foreach循环时相同的语义:线程要在所有工作后才继续运行。还要注意,如果任何操作抛出一个未处理的异常,你调用的paraller方法最后会抛出一个AggregateException。

// 存储用于配置 Parallel 类的方法的操作的选项。
public class ParallelOptions
{
// 初始化 ParallelOptions 类的新实例
public ParallelOptions();
// 获取或设置与此 ParallelOptions 实例关联的 CancellationToken,运行取消操作
public CancellationToken CancellationToken { get; set; }
// 获取或设置此 ParallelOptions 实例所允许的最大并行度,默认为-1(可用CPU数)
public int MaxDegreeOfParallelism { get; set; }
// 获取或设置与此 ParallelOptions 实例关联的 TaskScheduler。默认为TaskScheduler.Default
public TaskScheduler TaskScheduler { get; set; }
}

除此之外,For和ForEach方法有一些重载版本允许传递3个委托:

private static Int64 DirectoryBytes(String path, String searchPattern, SearchOption searchOption)
{
var files = Directory.EnumerateFiles(path, searchPattern, searchOption);
Int64 masterTotal = 0; ParallelLoopResult result = Parallel.ForEach<String, Int64>(files,
() =>
{
// localInit: 每个任务开始之前调用一次
// 每个任务开始之前,总计值都初始化为0
return 0;
}, (file, parallelLoopState, index, taskLocalTotal) =>
{
// body: 每个任务调用一次
// 获得这个文件的大小,把它添加到这个任务的累加值上
Int64 fileLength = 0;
FileStream fs = null;
try
{
fs = File.OpenRead(file);
fileLength = fs.Length;
}
catch (IOException) { /* 忽略拒绝访问的文件 */ }
finally { if (fs != null) fs.Dispose(); }
return taskLocalTotal + fileLength;
}, taskLocalTotal =>
{
// localFinally: 每个任务完成后调用一次
// 将这个任务的总计值(taskLocalTotal)加到中的总计值(masterTotal)上去
Interlocked.Add(ref masterTotal, taskLocalTotal);
});
return masterTotal;
}

每个任务都通过taskLocalTotal变量为分配给它的文件维护自己的总计值。每个任务完成工作之后,都调用Interlocked.Add方法[对两个 32 位整数进行求和并用和替换第一个整数],以一种线程安全的方式更新总的总计值。由于每个任务都有自己的总计值,可以在一个工作项处理期间,无需进行线程同步。由于线程同步会造成性能的损失,所以不需要线程同步是一件好事。只有在每个任务返回之后,masterTotal才需要以一种线程安全的方式更新materTotal变量。所以,因为调用Interlocked.Add方法而造成的性能损失每个任务只发生一次,而不会每个工作项都发生。

// 可用来使 Parallel 循环的迭代与其他迭代交互
public class ParallelLoopState
{
// 获取循环的任何迭代是否已引发相应迭代未处理的异常
public bool IsExceptional { get; }
// 获取循环的任何迭代是否已调用 Stop
public bool IsStopped { get; }
// 获取从中调用 Break 的最低循环迭代。
public long? LowestBreakIteration { get; }
// 获取循环的当前迭代是否应基于此迭代或其他迭代发出的请求退出。
public bool ShouldExitCurrentIteration { get; }
// 告知 Parallel 循环应在系统方便的时候尽早停止执行当前迭代之外的迭代。
public void Break();
// 告知 Parallel 循环应在系统方便的时候尽早停止执行。
public void Stop();
}

参与工作的每一个任务都会获得它自己的ParallelState对象,并可通过这个对象和参与工作的其他任务进行交互。Stop方法告诉循环停止处理任何更多的工作,未来对IsStopped属性的查询会返回true。Break方法告诉循环不再继续处理当前项之后的项。例如,假如ForEach被告知要处理100项,并在第5项时调用了Break,那么循环会确保前5项处理好之后,ForEach才返回。但注意,这并不是说在这100项中,只有前5项被处理,也许第5项之后可能在以前已经处理过了。LowestBreakIteration属性返回在处理过程中调用过Break方法的最低的项。从来没有调用过Break,LowestBreakIteration会返回null。

// 提供执行 System.Threading.Tasks.Parallel 循环的完成状态。
public struct ParallelLoopResult
{
// 获取该循环是否已运行完成(即该循环的所有迭代均已执行,并且该循环没有收到提前结束的请求)。
public bool IsCompleted { get; } // 获取从中调用 System.Threading.Tasks.ParallelLoopState.Break() 的最低迭代的索引。
public long? LowestBreakIteration { get; }
}

可通过检查属性来了解循环的结果,如果IsCompleted返回true。表明循环运行完成,所有项都得到了处理。如果IsCompleted为false,而且LowestBreakIteration为null,表明参与工作的某个线程调用了Stop方法。如果LowestBreakIteration返回false,而且LowestBreakIteration不为null,表名参与工作的某个线程调用的Break方法,LowestBreakIteration返回的Int64值指明了保证已得到处理的最低一项的索引。
场景
public void run(Action<List<string>> onload)
{
List<string> directoryLists = new List<string>();
directoryLists = Directory.GetDirectories(m_importPath).ToList();
Parallel.ForEach(directoryLists,new ParallelOptions { MaxDegreeOfParallelism=10}, i =>
{
List<string> files = importer(i);
onload(files);
}
}
Action<List<string>> onload = dir =>
{
BeginInvoke(new EventHandler((obj, even) =>
{
var root = new TreeNode(dir[0]);
for (int i = 1; i < dir.Count; i++)
{
string fileName = dir[i].Substring(dir[i].LastIndexOf('\\') + 1);
root.Nodes.Add(fileName.Remove(fileName.IndexOf('.')));
}
this.treeView1.Nodes.Add(root);
}), null);
};
import.run(onload);
Parallel线程使用的更多相关文章
- Parallel线程安全问题
废话不多说,上代码: using System; using System.Collections.Generic; using System.Threading.Tasks; namespace P ...
- 网络性能测试工具iperf详细使用图文教程
Iperf是一个网络性能测试工具.Iperf可以测试TCP和UDP带宽质量.Iperf可以测量最大TCP带宽,具有多种参数和UDP特性. Iperf可以报告带宽,延迟抖动和数据包丢失.利用Iper ...
- 网络性能测试工具iperf详细使用图文教程【转载】
原文:http://blog.163.com/hlz_2599/blog/static/142378474201341341339314/ 参考:http://man.linuxde.net/iper ...
- iperf 测试工具
Iperf是一个网络性能测试工具.Iperf可以测试TCP和UDP带宽质量.Iperf可以测量最大TCP带宽,具有多种参数和UDP特性. Iperf可以报告带宽,延迟抖动和数据包丢失.利用Iperf这 ...
- iperf使用指南
注意:iperf板上版本和PC上版本要一致,至少都要是2或者3,不能一个是2,一个是3. You also get a "connection refused" error whe ...
- 网络性能测试工具-Iperf
一.简单介绍 Iperf是一个网络性能测试工具,Iperf可以测试TCP和UDP带宽质量,Iperf可以测量最大TCP带宽,具有多种参数和UDP特性.Iperf可以报告带宽,延迟抖动和数据包丢失.利用 ...
- Iperf是一个网络性能测试工具
http://blog.163.com/hlz_2599/blog/static/142378474201341341339314/ Iperf是一个网络性能测试工具.Iperf可以测试TCP和UDP ...
- 网络性能测试工具iperf详细使用图文教程(转)
Iperf是一个网络性能测试工具.Iperf可以测试TCP和UDP带宽质量.Iperf可以测量最大TCP带宽,具有多种参数和UDP特性.Iperf可以报告带宽,延迟抖动和数据包丢失.利用Iperf这一 ...
- 【Linux】网络性能测试工具iperf详细使用图文教程【转】
参考链接:https://www.cnblogs.com/yingsong/p/5682080.html Iperf是一个网络性能测试工具.Iperf可以测试TCP和UDP带宽质量. Iperf可以测 ...
随机推荐
- 安装LockBox 3.7.0,用LockBox加密解密!
LockBox 官 方 网 站:http://lockbox.seanbdurkin.id.au/HomePage LockBox的Github 网址:https://github.com/S ...
- java获取当前日期等以及时区
代码: public static void main(String[] args) throws Exception{ /* * 获取当前时间的办法 */ //这个获取从1970年..直到现在的毫秒 ...
- #include <objsafe.h>//OCX控件在IE8浏览器下不能使用问题
一.OCX控件开发常见的问题 1.OCX控件在IE8浏览器下不能使用问题 原因:IE8会拦截OCX控件的方法. 解决方法:在OCX控件开发时加入安全接口. (1)在有"Crtl"字 ...
- PHP中include和require的区别详解
1.概要 require()语句的性能与include()相类似,都是包括并运行指定文件.不同之处在于:对include()语句来说,在执行文件时每次都要进行读取和评估:而对于require()来说, ...
- 2、NASA HS3(Hurricane AND Server Storm Sentinel)
国内访问不到,但是通过ppt可以看到,数据支撑做的很到位,前台展示很炫. 气象领域WebGL应用最好案例的当之无愧啊.这篇全部贴图了. 来自为知笔记(Wiz)
- mvc通过controller创建交互接口
public JsonResult Home(string userName, string password, string type) { List<person> list = ne ...
- JAVA的界面(Swing)
现在的程序很多在java中运行,很多时候是Web;很多服务端还是有一个简单的日志文件比较好:或者配置: 今天在看java图形界面开发时,看见已经不怎么更新的库.没有办法,市场决定一切,很多好的东西没有 ...
- window.returnValue跨域传值问题[转]
主页面用window.showModalDialog的时候,如果直接打开其它系统的页面,这时候别人的页面在window.returnValue=1;这样返回值的时候,主页面是取不到返回值的,原因就是因 ...
- (转)Silverlight 与 JS交互
转自 http://www.cnblogs.com/wt616/archive/2011/10/08/2201987.html 1.Silverlight直接调用JS的函数: 这个很简单,只要在HTM ...
- LR12.53—第2课:准备脚本重播
第2课:准备脚本重播 创建Vuser脚本后,可以通过从VuGen中运行它验证它.有时重播将失败,即使同样的动作在录制过程中取得了成功. 许多应用程序使用,每次使用应用程序时更改动态值.例如,某些服 ...