C# Parallel.For和Parallel.ForEach学习
2017-12-14 15:34
417 查看
《精通C#编程(第6版)》598页,“在次线程中访问UI元素”,按照书上的源代码程序总是无响应,百度后发现是线程死锁的原因;
参见
c#+Parallel.ForEach的卡死现象
使用了ThreadPool.QueueUserWorkItem改进书上例子。
3a.如果单个任务执行非常快以致于创建线程的开销远大于在当前线程执行剩余任务的开销,那么任务调度器不会创建其它工作线程,所有的Invoke都在当前线程得以执行,ForEach返回。
3b.如果创建线程可能加快任务处理速度,任务调度器会创建工作线程,并在工作线程上安排任务。
4b.在工作线程上执行的Invoke全部被阻塞,等待窗体线程进行处理。
5b.窗体线程执行所有可执行的任务后,等待ForEach返回,但由于其他线程在等待窗体线程处理Invoke,任务不能完成,ForEach无法返回,造成死锁。”
测试结果:
参见
c#+Parallel.ForEach的卡死现象
使用了ThreadPool.QueueUserWorkItem改进书上例子。
3a.如果单个任务执行非常快以致于创建线程的开销远大于在当前线程执行剩余任务的开销,那么任务调度器不会创建其它工作线程,所有的Invoke都在当前线程得以执行,ForEach返回。
3b.如果创建线程可能加快任务处理速度,任务调度器会创建工作线程,并在工作线程上安排任务。
4b.在工作线程上执行的Invoke全部被阻塞,等待窗体线程进行处理。
5b.窗体线程执行所有可执行的任务后,等待ForEach返回,但由于其他线程在等待窗体线程处理Invoke,任务不能完成,ForEach无法返回,造成死锁。”
public partial class MainForm : Form { public MainForm() 4000 { InitializeComponent(); } private void btnProcessImage_Click(object sender, EventArgs e) { DirectoryInfo dir = new DirectoryInfo(@"d:\samplePicture"); dir.Delete(true); dir = new DirectoryInfo(@"d:\samplePictureParallelForEach"); dir.Delete(true); dir = new DirectoryInfo(@"d:\samplePictureParallelFor"); dir.Delete(true); ThreadPool.QueueUserWorkItem(w => { ProcessImage(); }, null); ThreadPool.QueueUserWorkItem(w => { ProcessImageParallelFor(); }, null); ThreadPool.QueueUserWorkItem(w => { ProcessImageParallelForEach(); }, null); textBox1.AppendText("\r\n"); } private void ProcessImage() { Stopwatch sw = new Stopwatch(); sw.Start(); string[] files = Directory.GetFiles(@"d:\sample", "*.jpg", SearchOption.AllDirectories); string newDir = @"d:\samplePicture"; Directory.CreateDirectory(newDir); foreach(string currentfile in files) { string fileName = Path.GetFileName(currentfile); using (Bitmap bitMap = new Bitmap(currentfile)) { bitMap.RotateFlip(RotateFlipType.Rotate180FlipNone); bitMap.Save(Path.Combine(newDir, fileName)); Invoke((Action)delegate { Text = string.Format("Processing {0} on thread {1}", fileName, Thread.CurrentThread.ManagedThreadId); }); } } sw.Stop(); Invoke((Action)delegate { textBox1.AppendText(string.Format("\r\n正常Foreach循环耗时:{0} ", sw.Elapsed.TotalSeconds.ToString())); }); } //ParallelForEach 并行 private void ProcessImageParallelForEach() { Stopwatch sw2 = new Stopwatch(); sw2.Start(); string[] files = Directory.GetFiles(@"d:\sample", "*.jpg", SearchOption.AllDirectories); string newDir = @"d:\samplePictureParallelForEach"; Directory.CreateDirectory(newDir); Parallel.ForEach (files, currentfile => { string fileName = Path.GetFileName(currentfile); using (Bitmap bitMap = new Bitmap(currentfile)) { bitMap.RotateFlip(RotateFlipType.Rotate180FlipNone); bitMap.Save(Path.Combine(newDir, fileName)); Invoke((Action)delegate { Text = string.Format("Processing {0} on thread {1}", fileName, Thread.CurrentThread.ManagedThreadId); }); } } ); sw2.Stop(); Invoke((Action)delegate { textBox1.AppendText(string.Format("\r\n并行ForEach模式耗时:{0} ", sw2.Elapsed.TotalSeconds.ToString())); }); } //ParallelFor并行 private void ProcessImageParallelFor() { Stopwatch sw3 = new Stopwatch(); sw3.Start(); string[] files = Directory.GetFiles(@"d:\sample", "*.jpg", SearchOption.AllDirectories); string newDir = @"d:\samplePictureParallelFor"; Directory.CreateDirectory(newDir); Parallel.For(0, files.Length, (index) => { string[] filesTemp = Directory.GetFiles(@"d:\sample", "*.jpg", SearchOption.AllDirectories); string fileName = Path.GetFileName( filesTemp[index]); using (Bitmap bitMap = new Bitmap(filesTemp[index])) { bitMap.RotateFlip(RotateFlipType.Rotate180FlipNone); bitMap.Save(Path.Combine(newDir, fileName)); Invoke((Action)delegate { Text = string.Format("Processing {0} on thread {1}", fileName, Thread.CurrentThread.ManagedThreadId); }); } }); sw3.Stop(); Invoke((Action)delegate { textBox1.AppendText(string.Format("\r\n并行For模式耗时:{0} ", sw3.Elapsed.TotalSeconds.ToString())); }); } }
测试结果:
相关文章推荐
- C# 使用Parallel并行开发Parallel.For、Parallel.Foreach实例
- [C#] Parallel.For的线程数
- [C#] Parallel.For的线程数
- C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ForEach 呢?
- (转).NET 4.5中使用Task.Run和Parallel.For()实现的C# Winform多线程任务及跨线程更新UI控件综合实例
- C# 并行循环Parallel.For
- C# Parallel之for,foreach使用(笔记)
- [C#]『Parallel.For』『Parallel.ForEach』任务并行库使用小计
- c# Parallel.For 并行编程 执行顺序测试
- C#并行运算 Parallel.Invoke、Parallel.For、Parallel.Foreach性能测试及示例
- C# 使用Parallel并行开发Parallel.For、Parallel.Foreach实例
- C# 使用Parallel并行开发Parallel.For、Parallel.Foreach实例
- Parallel stepped for loops in .NET C# z
- Parallel for loops in .NET C# z
- C#使用Parallel类进行多线程编程实例
- JavaScript for C#Developers Study(2)
- Xamarin Mono For Android 4.6.07004 完整离线安装破解版(C#开发Android、IOS工具)
- 编写高质量代码改善C#程序的157个建议——建议18:foreach不能代替for
- 推荐VS2008插件CodeRush Xpress for C#