构建多线程应用程序2 Parallel 并行类:Parallel.ForEach()、Task异步操作类:Task.Factory.StartNew()、并行LINQ查询: AsParallel()
来源:互联网 发布:javascript功能 编辑:程序博客网 时间:2024/06/05 11:45
一、.NET平台下的并行编程
.NET 4发布了一个全新的并行编程库,使用 System.Threading.Tasks 中的类型,可以构建细粒度,可扩展的并行代码,而不必直接与线程和线程池打交道。此外,你还可以使用强类型的LINQ查询(通过并行LINQ,即PLINQ)来分配工作。
二、Parallel 并行类的作用
以并行的方式迭代数据集合(实现了IEnumerable<T>的对象)。
Parallel 并行类支持两个主要的静态方法(Parallel.For()和Parallel.ForEach())。
示例:使用foreach 阻塞方式处理图像数据
使用Parallel.ForEach 并行方式处理图像数据
效果:
代码:
using System.Threading.Tasks;
using System.Threading;
using System.IO;
按钮点击:
private void ProcessFiles() { //返回目录(包含子目录),所有文件名。如:C:\Pictures\1.jpg string[] files = Directory.GetFiles(@"C:\Pictures","*.jpg",SearchOption.AllDirectories); string newDir= @"C:\ModifiedPictures"; Directory.CreateDirectory(newDir);//创建目录 //阻塞方式处理图像数据 foreach(string currentFile in files) { string filename = Path.GetFileName(currentFile);//返回指定路径的文件名和扩展名。如:1.jpg using (Bitmap bitmap = new Bitmap(currentFile))//根据图片地址,得到图片 { bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);//旋转图片 bitmap.Save(Path.Combine(newDir, filename));//保存图片 this.textBox1.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId); } } //并行方式处理图像数据 //Parallel.ForEach 循环files(currentFile中的项) Parallel.ForEach(files, currentFile => { string filename = Path.GetFileName(currentFile);//返回指定路径的文件名和扩展名。如:1.jpg using (Bitmap bitmap = new Bitmap(currentFile))//根据图片地址,得到图片 { bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);//旋转图片 bitmap.Save(Path.Combine(newDir, filename));//保存图片 this.textBox1.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId); } }); this.textBox1.Text = "完成!"; }
三、Task异步操作类
Task 在次线程中调用方法
Task的Factory属性返回一个TaskFactory对象。
调用StartNew()方法时,传入一个Action<T>委托(这里为一个Lambda表达式),指向以异步方式进行调用的方法。
Task.Factory.StartNew(() => {
调用的方法
});
代码:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading.Tasks;using System.Threading;using System.IO;namespace WindowsFormsApplication1{ public partial class Form1 : Form { public Form1() { Control.CheckForIllegalCrossThreadCalls = false;//是否进行控件操作线程的检查 //1.在窗体构造函数中写Control.CheckForIllegalCrossThreadCalls =false; //2.使用Invoke等委托函数。问题原因是。 //net2.0以后拒绝多线程访问空间,避免空间造成死锁。 //以前Control.CheckForIllegalCrossThreadCalls =false;默认就是这样,现在默认为true。 //如果不会好几个线程同时操作一个控件用方法1就可以。 //如果存在多个线程一起操作控件使用方法2 // 方法2可以Invoke(new MethodInvoker(delegate(){//do something... })); InitializeComponent(); } private void btnProessImages_Click(object sender, EventArgs e) { //Task 在次线程中调用方法 //Task的Factory属性返回一个TaskFactory对象。 //调用StartNew()方法时,传入一个Action<T>委托(这里为一个Lambda表达式),指向以异步方式进行调用的方法。 Task.Factory.StartNew(() => { ProcessFiles(); }); } private void ProcessFiles() { //返回目录(包含子目录),所有文件名。如:C:\Pictures\1.jpg string[] files = Directory.GetFiles(@"C:\Pictures","*.jpg",SearchOption.AllDirectories); string newDir= @"C:\ModifiedPictures"; Directory.CreateDirectory(newDir);//创建目录 //阻塞方式处理图像数据 foreach(string currentFile in files) { string filename = Path.GetFileName(currentFile);//返回指定路径的文件名和扩展名。如:1.jpg using (Bitmap bitmap = new Bitmap(currentFile))//根据图片地址,得到图片 { bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);//旋转图片 bitmap.Save(Path.Combine(newDir, filename));//保存图片 this.textBox1.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId); } } this.textBox1.Text = "完成!"; } }}
4.5框架,支持 Task.Run()。是把 await 之后的内容包装起来放到新的线程环境去执行
async必须加在函数声明处,如果不加async关键字,函数内部不能使用await关键字,仅仅如此
await只能用来等待一个Task或者Task<T>进行异步执行返回
实例1:
//异步方法 public async Task<int> MethodA(DateTime bgtime, int i) { int r = await Task.Run(() => { Console.WriteLine("异步方法{0}Task被执行", i); Thread.Sleep(100); return i * 2; }); Console.WriteLine("异步方法{0}执行完毕,结果{1}", i, r); if (i == 49) { Console.WriteLine("用时{0}", (DateTime.Now - bgtime).TotalMilliseconds); } return r; }
调用:
public static void ACTest()
{Asy_ClassA asy = new Asy_ClassA();
DateTime abgtime = DateTime.Now;
for (int i = 0; i < 50; i++)
{
asy.MethodA(abgtime, i);
Console.WriteLine("异步方法{0}调用完成", i);
}
}
实例2:
class Program { private static async void Test() { Task<int> t = new Task<int>(() => { Thread.Sleep(3000); return 1; }); t.Start(); int tr = await t; Console.WriteLine(tr); } static void Main(string[] args) { Test(); Console.WriteLine("Main"); Console.ReadKey(); } }
四、并行LINQ查询(PLINQ)
System.Linq命名空间的ParallelEnumerable
1、AsParallel() 启用查询并行化
2、WithCancellation() 指示PLINQ应定时监视取消标记状态
截面:
代码:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading.Tasks;using System.Threading;using System.IO;namespace WindowsFormsApplication1{ public partial class Form1 : Form { private CancellationTokenSource cancelToken = new CancellationTokenSource();//取消标记 public Form1() { InitializeComponent(); } private void btnExecute_Click(object sender, EventArgs e) { ProcessIntData(); } private void btnCancle_Click(object sender, EventArgs e) { cancelToken.Cancel();//取消 } private void ProcessIntData() { //获得很大的整数数组 int[] source = Enumerable.Range(1, 10000000).ToArray(); //找到num%3==0为True 的数字,降序返回 int[] modThreeIsZero = null; try { //AsParallel()启用查询并行化 //WithCancellation() 指示PLINQ应定时监视取消标记状态 modThreeIsZero = (from num in source.AsParallel().WithCancellation(cancelToken.Token) where num % 3 == 0 orderby num descending select num).ToArray(); } catch (OperationCanceledException ex) { this.textBox1.Text = ex.Message; } MessageBox.Show(string.Format("发现{0}个数", modThreeIsZero.Count())); } }}
- 构建多线程应用程序2 Parallel 并行类:Parallel.ForEach()、Task异步操作类:Task.Factory.StartNew()、并行LINQ查询: AsParallel()
- Task Parallel.For、Parallel.ForEach、Parallel.Invoke
- Parallel.ForEach() 并行循环
- Parallel.ForEach() 并行循环
- C#并行开发_Thread/ThreadPool, Task/TaskFactory, Parallel
- C#并行开发_Thread/ThreadPool, Task/TaskFactory, Parallel
- C#并行开发_Thread/ThreadPool, Task/TaskFactory, Parallel
- C# 使用Parallel并行开发Parallel.For、Parallel.Foreach实例
- Oracle并行操作——并行查询(Parallel Query)
- Task+ConcurrentQueue+Parallel多线程编程
- Oracle 并行查询 parallel Query
- Oracle 并行查询 parallel Query
- Oracle 并行查询 parallel Query
- Task 多线程 并行
- 用Parallel和foreach包玩转并行计算
- Task.Run vs Task.Factory.StartNew
- Task.Run Vs Task.Factory.StartNew
- C#并行运算 Parallel.Invoke、Parallel.For、Parallel.Foreach性能测试及示例
- 学习鸟哥的Linux私房菜笔记(5)——目录
- 五角星填充FillModesClassical
- 函数中关于“函数声明”“函数定义”“函数原型”的辨析
- [隐式图搜索]Fill(倒水问题) UVA10603
- 在silverlight中EnitityFramework4.1框架下的以codefirst模式进行后台处理的SQL日志记录方法
- 构建多线程应用程序2 Parallel 并行类:Parallel.ForEach()、Task异步操作类:Task.Factory.StartNew()、并行LINQ查询: AsParallel()
- 基数排序的一个例子
- WMI--Windows API--SWbemLocator Object
- 绘制花朵Flower
- 揭秘JavaScript中谜一样的this
- DLL Hell
- ZTE VX10 H618B不增加设备、不拆机、不破解,开启自带路由+iTV的详细设置方法
- .NET MVC 扩展方法必须在非泛型静态类中定义
- 30个你必须记住的CSS选择符