>>返回《C# 并发编程》
html
如今咱们先说明几个概念:数据库
Task
和 Task<TResult>
类型实现将来模式,在老式异步编程 API 中,采用回调或事件(event)async
和 await
解决的问题async
方法在开始时以同步方式执行。在 async
方法内部,运行到await
关键字会执行一个异步等待
async
方法,并返回,留下一个未完成的 task
。await
住的操做完成,async
方法就恢复运行(不必定是原来的线程,具体看同步上下文的配置)。await
语句等待一个任务完成,这时会捕捉同步上下文。
SynchronizationContext
不为空,这个上下文就是当前 SynchronizationContext
。SynchronizationContext
为空,则这个上下文为当前 TaskScheduler。注意: 最好的作法是,在核心库代码中一直使用
ConfigureAwait
。在外围的用户界面代码中,只在须要时才恢复上下文。编程
Task.Run
await
关键字,将任务交给线程池完成,解决读取时窗体卡顿状况TaskFactory.StartNew
TaskCompletionSource<T>
。
TaskCompletionSource<T>
。await
抛出的异常,咱们更想要try { await Task.Run(() => throw new NotSupportedException()); } catch (Exception ex) { //print: NotSupportedException Console.WriteLine(ex.GetType().Name); }
Wait()
方法,异常类型被包装try { Task task = Task.Run(() => throw new NotSupportedException()); task.Wait(); } catch (Exception ex) { //print: AggregateException Console.WriteLine(ex.GetType().Name); }
反面教材: 以前在工做中出现一块儿事故,实施好的项目,3个月后天天凌晨出现大量设备掉线的状况。服务器
- 因为数据超时时间时3个月,并且发现出现问题的日志和数据清理发生时间有关联关系
- 排查代码发现文件清理器,清理数据使用的Parallel类,并行删除文件,并且没有对并发数限制
- 文件清理器运行时,致使服务器性能急剧降低,形成处理设备消息延迟,心跳超时致使掉线
- 重构了文件清理器代码,解决了这个问题
不保证顺序执行。多线程
//ForEach int[] arr = new int[] { 1, 2, 3, 4 }; Parallel.ForEach(arr, item => Console.Write(item)); System.Console.WriteLine(); //PLINQ var sum = arr.AsParallel().Select(item => item * 2).Sum(); System.Console.WriteLine($"sum:{sum}."); //Invoke int num = 10; Parallel.Invoke( () => num += 2, () => num -= 2, () => num -= num, () => num += 2 ); System.Console.WriteLine($"num:{num}."); /* print: 1243 sum:20. num:0. */
系统会把这些异常封装在 AggregateException 类里,在程序中抛给代码。 这一特色对全部方法都是同样的,包括 Parallel.ForEach、Paralle.lInvoke、Task.Wait 等。 AggregateException 类型有几个实用的 Flatten 和 Handle 方法,用来简化错误处理的代码:闭包
try { Parallel.Invoke(() => { throw new Exception(); }, () => { throw new Exception(); }); } catch (AggregateException ex) { ex.Handle(exception => { Console.WriteLine(exception); return true; //“已经处理” }); }
在编写任务并行程序时,要格外留意下闭包(closure)捕获的变量。 记住闭包捕获的是引用(不是值),所以能够在结束时以不明显地方式地分享这些变量。并发
若是事件中带有参数,那么最好 采用响应式编程,而不是常规的事件处理程序。异步
//System.Runtime.dll namespace:System 中定义了这些接口 interface IObserver<in T> { void OnNext(T item); void OnCompleted(); void OnError(Exception error); } interface IObservable<out T> { IDisposable Subscribe(IObserver<T> observer); }
Rx(Rx-Main)中定义了响应式编程的封装,后面会有介绍。async