请大家关注我的微博:@NormanLin_BadPixel坏像素
废话不多说,先去看大神们的教程吧。
C#:异步编程和线程的使用(.NET 4.5 )
本引用文是由葡萄城控件技术开发团队发布,转载请注明出处:葡萄城控件
这里我会从大佬的原文中摘取一些我认为重要的话。
.NET中提供了三种不同的异步模式:
1. 异步编程模型(APM)模式
2. 基于事件的异步模式(EAP)
3. 基于任务的异步模式(TAP)
前两种模型微软官方并不推荐使用,本文不再详细描述。我们将详细讨论基于任务的异步模式(TAP):
在.NET 4.5中引入了异步编程模式,大部分情况下都不需要我们手动创建线程。编译器已经替代了开发人员来完成这项工作。
.NET框架引入了两个新的关键字来实现异步编程:“async”和“await”。使用 “await”的异步方法必须由“async”修饰符来声明方法。“await”关键字修饰调用异步方法。await 运算符应用于一个异步方法中的任务以挂起该方法的执行,直到等待任务完成.
而“ async ”修饰符只能用于返回值为Task类型或Void的方法。它不能用于主程序的切入点。所有的方法之前不能使用await关键字,使用“await”关键字方法必须返回 “可等待”类型。以下属于“可等待”类型:
1. Task
2. Task
3. 自定义“可等待”类型。
1: private async static void CallerWithAsync()// async modifier is used
2:
3: {
4:
5: string result = await GetSomethingAsync();// await is used before a method call. It suspends
6: //execution of CallerWithAsync() method and control returs to the calling thread that can
//perform other task.
7:
8: Console.WriteLine(result);
9: // this line would not be executed before GetSomethingAsync() //method completes
10:
11: }
我觉得这段代码很重要,能帮助大家理解这里的执行顺序。大家看英语大概都能看懂。真的难以理解的,大家可以把它想象成Unity的协程。
1: private async static void MultipleAsyncMethodsWithCombinators()
2:
3: {
4:
5: Task t1 = GreetingAsync("Bulbul");
6:
7: Task t2 = GreetingAsync("Ahmed");
8:
9: await Task.WhenAll(t1, t2);
10:
11: Console.WriteLine("Finished both methods.\n " +
12:
13: "Result 1: {0}\n Result 2: {1}", t1.Result, t2.Result);
14:
15: }
在这里,我们使用Task.WhenAll连接器。Task.WhenAll创建一个任务,将完成所有的提供的任务。Task类也有其他的结合器。Task.WhenAny,当所任务链中所有的任务完成时,结束使用。
在此之前,如果从线程池中调用线程,线程是不可能取消。现在,Task类提供了一个方法基于CancellationTokenSource类能够取消已启动的任务
对这个取消已启动的任务,我有一些疑惑,它是在调用了这个方法后就一直在监听这个CancellationToken是否结束了还是只有在调用这个方法的时候判断。所以,我在原来的代码那里,做了一些修改。
Thread.Sleep(5000);
token.ThrowIfCancellationRequested();
这段代码会在5秒后抛出The operation was canceled. 错误。
token.ThrowIfCancellationRequested();
Thread.Sleep(5000);
不会抛出错误,程序正常运行。
经过这次实验,我们确定了只有在调用token.ThrowIfCancellationRequested()这个方法的时候判断是否要抛出错误
For或ForEach方法可以在多线程中和且索引无序可以是无序的。
如果想停止并行For或ForEach方法,可通过ParallelLoopState作为参数,并根据需要打破循环的状态,跳出循环。
ParallelLoopResult result =
Parallel.For(0, 100, async (int i, ParallelLoopState pls) =>
{
Console.WriteLine("{0}, task: {1}, thread: {2}", i,
Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
await Task.Delay(10);
if (i > 5) pls.Break();
});
这段代码有点问题的,因为它是在await完之后再判断pls的break,不会起到什么作用。这样改就好理解了。
ParallelLoopResult result =
Parallel.For(0, 100, async (int i, ParallelLoopState pls) =>
{
if (i > 5) pls.Break();
await Task.Delay(10);
Console.WriteLine("{0}, task: {1}, thread: {2}", i,
Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
});