并行委托
并行委托有Parallel.For()、Parallel.Foreach<>()、Parallel.Invoke()三种写法,应用并行可以缩短程序运行时间。
Parallel.For()写法:
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
//【写法一】
//Parallel.For(1, 11, new DelegateHelper().Test);
//【写法二】
Parallel.For(1, 11, delegate(int i) {
Console.WriteLine(i); Thread.Sleep(1000);
});
watch.Stop();
//非并行情况下循环10次需要10s,因为每次执行Test方法会休息1s
Console.WriteLine("花费时间:" + watch.Elapsed.Seconds);
Console.ReadKey();
}
public void Test(int num)
{
Console.WriteLine(num);
Thread.Sleep(1000);
}
运行截图如下:
Parallel.Foreach<>()写法:
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
//【写法一】
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
string[] strArray = { "a","b","c","d","e","f","g"};
//Parallel.ForEach<int>(nums, new DelegateHelper().Test);
//【写法二】
Parallel.ForEach<int>(nums, delegate(int num)
{
Console.WriteLine(num);
Thread.Sleep(1000);
});
//遍历string数组
Parallel.ForEach<string>(strArray, delegate(string str)
{
Console.WriteLine(str);
Thread.Sleep(1000);
});
watch.Stop();
//非并行情况下循环10次需要10s,因为每次执行Test方法会休息1s
Console.WriteLine("花费时间:" + watch.Elapsed.Seconds);
Console.ReadKey();
}
public void Test(int num)
{
Console.WriteLine(num);
Thread.Sleep(1000);
}
运行结果如下:
Parallel.Invoke()写法:
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
//【写法一】
Action[] actions=new Action[]{
new Action(delegate(){Console.WriteLine("方法一");Thread.Sleep(1000);}),
new Action(delegate(){Console.WriteLine("方法二");Thread.Sleep(1000);}),
new Action(delegate(){Console.WriteLine("方法三");Thread.Sleep(1000);})
};
Parallel.Invoke(actions);
//【写法二】
Parallel.Invoke(Func1, Func2, Func3);
watch.Stop();
//非并行情况下循环10次需要10s,因为每次执行Test方法会休息1s
Console.WriteLine("花费时间:" + watch.Elapsed.Seconds);
Console.ReadKey();
}
public static void Func1()
{
Console.WriteLine("方法一"); Thread.Sleep(1000);
}
public static void Func2()
{
Console.WriteLine("方法二"); Thread.Sleep(1000);
}
public static void Func3()
{
Console.WriteLine("方法三"); Thread.Sleep(1000);
}
运行截图如下:
异步委托
异步委托可以异步执行委托的方法,不过是用EndInvoke()方法等待委托执行完毕然后获取返回值。
EndInvoke()会阻塞主线程,等到委托的方法执行完毕后,程序才会继续执行,不过EndInvoke()之前的代码会正常执行,一般用于执行相互独立的模块,BeginInvoke异步执行独立模块A,BeginInvoke之后EndInvoke之前执行独立模块B,等到两模块都执行完毕后来进行下一步的操作,这样可以提高一点效率。
没有回调函数:
public void AsyncDelegateNoCallback()
{
SayHiEventHandler sayHi = SayHiByChinese;
IAsyncResult iasyncResult = sayHi.BeginInvoke("蝈蝈", null, null);
Console.WriteLine("do some things......");
//有EndInvoke结果如图一,没EndInvoke结果如图二
//string result = sayHi.EndInvoke(iasyncResult);
Console.WriteLine("继续执行");
}
public string SayHiByChinese(string name)
{
Console.WriteLine("你好:" + name);
Thread.Sleep(2000);
return "成功";
}
有回调函数:
异步委托所需的回调函数其实就是无返回值、包含一个IAsyncResult类型参数的委托。
回调函数是在委托执行完毕之后才执行,此时EndInvoke()将不会再花费大量时间,因为委托已经执行完毕可直接获取结果。
public void AsyncDelegate()
{
SayHiEventHandler sayHi = SayHiByChinese;
IAsyncResult iasyncResult = sayHi.BeginInvoke("蝈蝈",CallBackFunc,"回调函数所需参数");
//回调函数中有EndInvoke,此处不应该再写一次
//sayHi.EndInvoke(iasyncResult);
Console.WriteLine("继续执行主线程");
}
public void AsyncDelegateAnonymous()
{
SayHiEventHandler sayHi = SayHiByChinese;
IAsyncResult iasyncResult = sayHi.BeginInvoke("蝈蝈", new AsyncCallback(delegate(IAsyncResult ias) {
AsyncResult asyncResult = ias as AsyncResult;
//param="回调函数所需参数"
string param = asyncResult.AsyncState.ToString();
SayHiEventHandler current = asyncResult.AsyncDelegate as SayHiEventHandler;
Console.WriteLine("do other things......");
//result="成功"
string result = current.EndInvoke(asyncResult);
Console.WriteLine("继续执行回调函数");
}), "回调函数所需参数");
//回调函数中有EndInvoke,此处不应该再写一次
//sayHi.EndInvoke(iasyncResult);
Console.WriteLine("继续执行主线程");
}
public void CallBackFunc(IAsyncResult ias)
{
AsyncResult asyncResult = ias as AsyncResult;
//param="回调函数所需参数"
string param = asyncResult.AsyncState.ToString();
SayHiEventHandler current = asyncResult.AsyncDelegate as SayHiEventHandler;
Console.WriteLine("do other things......");
//result="成功"
string result = current.EndInvoke(asyncResult);
Console.WriteLine("继续执行回调函数");
}
运行结果如图: