当前位置: 首页 > news >正文

信息平台网站建设国内的优秀网站

信息平台网站建设,国内的优秀网站,视频拍摄策划方案,wordpress 判断分页传送门#xff1a;异步编程系列目录…… 环境#xff1a;VS2012#xff08;尽管System.Threading.Tasks在.net4.0就引入#xff0c;在.net4.5中为其增加了更丰富的API及性能提升#xff0c;另外关键字”async”和”await”是在C#5.0引入的。vs2010打 Visual Studio Async …传送门异步编程系列目录…… 环境VS2012尽管System.Threading.Tasks在.net4.0就引入在.net4.5中为其增加了更丰富的API及性能提升另外关键字”async”和”await”是在C#5.0引入的。vs2010打 Visual Studio Async CTP for VS2010补丁可以引入关键字”async”和”await”的支持但是得不到.net4.5新增API的支持 CTPCommunity Test Preview 社区测试试用版就是一般的测试版本 术语 APM           异步编程模型Asynchronous Programming Model EAP           基于事件的异步编程模式Event-based Asynchronous Pattern TAP           基于任务的异步编程模式Task-based Asynchronous Pattern 我常常收到来自开发人员的一些问题这些问题主要集中在C#和Visual Basic中的新关键字”async”和”await”。我已经将这些问题分类整理并借此机会分享给大家。 概念概述 1.         从哪能获得关于”async”和”await”主题的优秀资源 通常你能在Visual Studio Async主题中找到很多资源eg文章、视频、博客等等。2011年10月份的MSDN杂志包含了三篇介绍”async”和”await”主题的优秀文章。如果你阅读我推荐你阅读顺序依次为 1) 《通过新的 Visual Studio Async CTP 更轻松地进行异步编程》 2) 《通过 Await 暂停和播放》 3) 《了解 Async 和 Await 的成本》 .NET团队博客同样也有”async”和”await”主题的优秀资源《Async in .NET4.5: 值得期待》 2.         为什么需要编译器帮助我们完成异步编程 Anders Hejlsberg’s在2011 微软Build大会上花了1个小时来帮我们说明为什么编译器在这里真的有用视频《C#和Visual Basic未来的发展方向》。简而言之传统的异步编程模型APM或EAP要求你手写大量代码eg连续传递委托、回调来实现并且这些代码会导致语句控制流混乱颠倒。通过.NET4.5提供的新的编程模型TAP你可以像在写同步代码一样使用常规的顺序控制流结合并行任务及”async”和”await”关键字来完成异步编程编译器在后台应用必要的转换以使用回调方式来避免阻塞线程。 3.         通过Task.Run() 将同步方法包装成异步任务是否真的有益处 这取决于你的目标你为什么要异步调用方法。如果你的目标只是想将当前任务切换到另一个线程执行比如保证UI线程的响应能力那么肯定有益。如果你的目标是为了提高可扩展性那么使用Task.Run() 包装成异步调用将没有任何实际意义。更多信息请看《我是否应该公开同步方法对应的异步方法API》。通过Task.Run() 你可以很轻松的实现从UI线程分担工作到另一个工作线程且可协调后台线程一旦完成工作就返回到UI线程。这里说的可扩展性就如当增加cpu时Task.Run()并不会增加程序的并行效率因为他只相当于启动了一个线程执行任务倘若使用Parallel.For就具有更好的可扩展性。什么是系统的可扩展性 “async”关键字 1.         将关键字”async”应用到方法上的作用是什么 当你用关键字”async”标记一个方法时即告诉了编译器两件事 1)         你告诉编译器想在方法内部使用”await”关键字只有标记了”async”关键字的方法或lambda表达式才能使用”await”关键字。这样做后编译器会将方法转化为包含状态机的方法类似的还有yield的工作原理请看 《C#稳固基础传统遍历与迭代器》 编译后的方法可以在await处挂起并且在await标记的任务完成后异步唤醒。 2)         你告诉编译器方法的结果或任何可能发生的异常都将作为返回类型返回。如果方法返回Task或TaskTResult这意味着任何结果值或任何在方法内部未处理的异常都将存储在返回的Task中。如果方法返回void这意味着任何异常会被传播到调用者上下文。 a)         async void函数只能在UI Event回调中使用。 b)         async void函数中一定要用try-catch捕获所有异常否则会很容易导致程序崩溃。另外需要特别注意lambda表达式 如ListT 只有 public void ForEach(ActionT action); 重载 1 Enumerable.Range(0, 3).ToList().ForEach(async (i) { throw new Exception(); }); 这段代码就隐式生成了async void 函数直接导致了程序的crash。 不过好在编译器是优先考虑生成 async Task 形式的匿名函数的。即如下两个重载编译器是使用ForEach(FuncT, Task action);重载生成async Task 函数。 1 2 public void ForEach(ActionT action); public void ForEach(FuncT, Task action); c)         注册TaskScheduler.UnobservedTaskException事件记录Task中未处理异常信息方便分析及错误定位。 2.         被”async”关键字标记的方法的调用都会强制转变为异步方式吗 不会当你调用一个标记了”async”关键字的方法它会在当前线程以同步的方式开始运行。所以如果你有一个同步方法它返回void并且你做的所有改变只是将其标记的”async”这个方法调用依然是同步的。返回值为Task或TaskTResult也一样。 方法用”async”关键字标记不会影响方法是同步还是异步运行并完成而是它使方法可被分割成多个片段其中一些片段可能异步运行这样这个方法可能异步完成。这些片段界限就出现在方法内部显示使用”await”关键字的位置处。所以如果在标记了”async”的方法中没有显示使用”await”那么该方法只有一个片段并且将以同步方式运行并完成。 3.         “async”关键字会导致调用方法被排队到ThreadPool吗会创建一个新的线程吗 全都不会”async”关键字指示编译器在方法内部可能会使用”await”关键字这样该方法就可以在await处挂起并且在await标记的任务完成后异步唤醒。这也是为什么编译器在编译”async” 标记的方法时方法内部没有使用”await”会出现警告的原因warning CS4014: 由于不等待此调用因此会在此调用完成前继续执行当前方法。请考虑向此调用的结果应用await运算符。 4.         ”async”关键字能标记任何方法吗 不能只有返回类型为void、Task或TaskTResult的方法才能用”async”标记。并且并不是所有返回类型满足上面条件的方法都能用”async”标记。如下我们不允许使用”async”标记方法 1)         在程序的入口方法egMain()不允许。当你正在await的任务还未完成但执行已经返回给方法的调用者了。EgMain()这将退出Main()直接导致退出程序。 2)         在方法包含如下特性时不允许。 l  [MethodImpl(MethodImplOptions.Synchronized)] 为什么这是不允许的详细请看《What’s New for Parallelism in .NET 4.5 Beta》。此特性将方法标记为同步类似于使用lock/SyncLock同步基元包裹整个方法体。 l  [SecurityCritical]和[SecuritySafeCritical]   (Critical关键) 编译器在编译一个”async”标记的方法原方法体实际上最终被编译到新生成的MoveNext()方法中但是其标记的特性依然存在。这意味着特性如[SecurityCritical]不会正常工作。 3)         在包含ref或out参数的方法中不允许。调用者期望方法同步调用完成时能确保设置参数值但是标记为”async”的方法可能不能保证立刻设置参数值直到异步调用完成。 4)         Lambda被用作表达式树时不允许。异步lambda表达式不能被转换为表达式树。 5.         是否有任何约定这时应该使用”async”标记方法 有基于任务的异步编程模型(TAP)是完全专注于怎样实现异步方法这个方法返回Task或TaskTResult。这包括(但不限于)使用”async”和”await”关键字实现的方法。想要深入TAP请看《基于任务的异步编程模型》文档。 6.         “async”标记的方法创建的Tasks是否需要调用”Start()” 不需要TAP方法返回的Tasks是已经正在操作的任务。你不仅不需要调用”Start()”而且如果你尝试也会失败。更多细节请看《.NET4.X 并行任务中Task.Start()的FAQ》 。 7.         “async”标记的方法创建的Tasks是否需要调用”Dispose()” 不需要一般来说你不需要 Dispose() 任何任务。请看《.NET4.X并行任务Task需要释放吗》。 8.         “async”是如何关联到当前SynchronizationContext 对于”async” 标记的方法如果返回Task或TaskTResult则没有方法级的SynchronizationContext交互对于”async” 标记的方法如果返回void则有一个隐藏的SynchronizationContext交互。 当一个”async void”方法被调用方法调用的开端将捕获当前SynchronizationContext(“捕获”在这表示访问它并且将其存储)。如果这里有一个非空的SynchronizationContext将会影响两件事前提”async void” 1)         在方法调用的开始将导致调用捕获SynchronizationContext.OperationStarted()方法并且在完成方法的执行时(无论是同步还是异步)将导致调用捕获SynchronizationContext.OprationCompleted()方法。这给上下文引用计数未完成异步操作提供时机点。如果TAP方法返回Task或TaskTResult调用者可通过返回的Task做到同样的跟踪。 2)         如果这个方法是因为未处理的异常导致方法完成那么这个异常将会提交给捕获的SynchronizationContext。这给上下文一个处理错误的时机点。如果TAP方法返回Task或TaskTResult调用者可通过返回的Task得到异常信息。 当调用”async void”方法时如果没有SynchronizationContext没有上下文被捕获然后也不会调用OperaionStarted/OperationCompleted方法。在这种情况下如果存在一个未处理过的异常在ThreadPool上传播那么这会采取线程池线程默认行为即导致进程被终止。 “await”关键字 1.         “await”关键字做了什么 “await”关键字告诉编译器在”async”标记的方法中插入一个可能的挂起/唤醒点。 逻辑上这意味着当你写”await someObject;”时编译器将生成代码来检查someObject代表的操作是否已经完成。如果已经完成则从await标记的唤醒点处继续开始同步执行如果没有完成将为等待的someObject生成一个continue委托当someObject代表的操作完成的时候调用continue委托。这个continue委托将控制权重新返回到”async”方法对应的await唤醒点处。 返回到await唤醒点处后不管等待的someObject是否已经经完成任何结果都可从Task中提取或者如果someObject操作失败发生的任何异常随Task一起返回或返回给SynchronizationContext。 在代码中意味着当你写 await someObject; 编译器会生成一个包含 MoveNext 方法的状态机类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 private class FooAsyncStateMachine : IAsyncStateMachine {     // Member fields for preserving “locals” and other necessary     state     int $state;     TaskAwaiter $awaiter;     …     public void MoveNext()     {         // Jump table to get back to the right statement upon         resumption         switch (this.$state)         {             …         case 2: goto Label2;             …         }         …         // Expansion of “await someObject;”         this.$awaiter someObject.GetAwaiter();         if (!this.$awaiter.IsCompleted)         {             this.$state 2;             this.$awaiter.OnCompleted(MoveNext);             return;             Label2:         }         this.$awaiter.GetResult();         …     } } 在实例 someObject上使用这些成员来检查该对象是否已完成通过 IsCompleted如果未完成则挂接一个续体通过 OnCompleted当所等待实例最终完成时系统将再次调用 MoveNext 方法完成后来自该操作的任何异常将得到传播或作为结果返回通过 GetResult并跳转至上次执行中断的位置。 2.         什么是”awaitables”什么是”awaiters” 虽然Task和TaskTResult是两个非常普遍的等待类型(“awaitable”)但这并不表示只有这两个的等待类型。 “awaitable”可以是任何类型它必须公开一个GetAwaiter() 方法并且返回有效的”awaiter”。这个GetAwaiter() 可能是一个实例方法eg:Task或TaskTResult的实例方法或者可能是一个扩展方法。 “awaiter”是”awaitable”对象的GetAwaiter()方法返回的符合特定的模式的类型。”awaiter”必须实现System.Runtime.CompilerServices.INotifyCompletion接口并可选的实现System.Runtime.CompilerServices.ICriticalNotifyCompletion接口。除了提供一个INotifyCompletion接口的OnCompleted方法实现可选提供ICriticalNotifyCompletion接口的UnsafeCompleted方法实现还必须提供一个名为IsCompleted的Boolean属性以及一个无参的GetResult()方法。GetResult()返回void如果”awaitable”代表一个void返回操作或者它返回一个TResult如果”awaitable”代表一个TResult返回操作。 几种方法来实现自定义的”awaitable” 谈论请看《await anything》。也能针对特殊的情景实现自定义”awaitable”请看《Advanced APM Consumption in Async Methods》和《Awaiting Socket Operations》。 3.         哪些地方不能使用”await” 1)         在未标记”async”的方法或lambda表达式中不能使用”await”。”async”关键字告诉编译器其标记的方法内部可以使用”await”。更详细请看《Asynchrony in C# 5 Part Six: Whither async?》 2)         在属性的getter或setter访问器中不能使用”await”。属性的意义是快速的返回给调用者因此不期望使用异步异步是专门为潜在的长时间运作的操作。如果你必须在你的属性中使用异步你可以通过实现异步方法然后在你的属性中调用。 3)         在lock/SyncLock块中不能使用”await”。关于谈论为什么不允许以及SemaphoreSlim.WaitAsync哪一个能用于此情况的等待请看《What’s New for Parallelism in .NET 4.5 Beta》。你还可以阅读如下文章关于如何构建各种自定义异步同步基元 a)         构建Async同步基元Part 1 AsyncManualResetEvent b)         构建Async同步基元Part 2 AsyncAutoResetEvent c)         构建Async同步基元Part 3 AsyncCountdownEvent d)         构建Async同步基元Part 4 AsyncBarrier e)         构建Async同步基元Part 5 AsyncSemaphore f)          构建Async同步基元Part 6 AsyncLock g)         构建Async同步基元Part 7 AsyncReaderWriterLock 4)         在unsafe区域中不能使用”await”。注意你能在标记”async”的方法内部使用”unsafe”关键字但是你不能在unsafe区域中使用”await”。 5)         在catch块和finally块中不能使用”await”。你能在try块中使用”await”不管它是否有相关的catch块和finally块但是你不能在catch块或finally块中使用”await”。这样做会破坏CLR的异常处理。 6)         LINQ中大部分查询语法中不能使用”await”。”await”可能只用于查询表达式中的第一个集合表达式的”from”子句或在集合表达式中的”join”子句。 4.         “await task;”和”task.Wait”效果一样吗 不。 “task.Wait()”是一个同步可能阻塞的调用。它不会立刻返回到Wait()的调用者直到这个任务进入最终状态这意味着已进入RanToCompletionFaulted或Canceled完成状态。相比之下”await task;”告诉编译器在”async”标记的方法内部插入一个隐藏的挂起/唤醒点这样如果等待的task没有完成异步方法也会立马返回给调用者当等待的任务完成时唤醒它从隐藏点处继续执行。当”await task;”会导致比较多应用程序无响应或死锁的情况下使用“task.Wait()”。更多信息请看《Await, and UI, and deadlocks! Oh my!》。 当你使用”async”和”await”时还有其他一些潜在缺陷。Eg 1)         避免传递lambda表达式的潜在缺陷 2)         保证”async”方法不要被释放 3)         不要忘记完成你的任务 4)         使用”await”依然可能存在死锁 5.         “task.Result”与”task.GetAwaiter().GetResult()”之间存在功能区别吗 存在。但仅仅在任务以非成功状态完成的情况下。如果task是以RanToCompletion状态完成那么这两个语句是等价的。然而如果task是以Faulted或Canceled状态完成task.Result将传播一个或多个异常封装而成的AggregateException对象而”task.GetAwaiter().GetResult()”将直接传播异常(如果有多个任务它只会传播其中一个)。关于为什么会存在这个差异请看《.NET4.5中任务的异常处理》。 6.         “await”是如何关联到当前SynchronizationContext 这完全取决于被等待的类型。对于给定的”awaitable”编译器生成的代码最终会调用”awaiter”的OnCompleted()方法并且传递将执行的continue委托。编译器生成的代码对SynchronizationContext一无所知仅仅依赖当等待的操作完成时调用OnCompleted()方法时所提供的委托。这就是OnCompleted()方法它负责确保委托在”正确的地方”被调用”正确的地方”完全由”awaiter”决定。 正在等待的任务(由Task和TaskTResult的GetAwaiter方法分别返回的TaskAwaiter和TaskAwaiterTResult类型)的默认行为是在挂起前捕获当前的SynchronizationContext然后等待task的完成如果能捕获到当前的SynchronzationContext调用continue委托将控制权返回到SynchronizationContext中。所以例如如果你在应用程序的UI线程上执行”await task;”如果当前SynchronizationContext非空则将调用OnCompleted()并且在任务完成时将使用UI的SynchronizationContext传播continue委托返回到UI线程。 当你等待一个任务如果没有当前SynchronizationContext那么系统会检查当前的TaskScheduler如果有当task完成时将使用TaskScheduler调度continue委托。 如果SynchronizationContext和TaskScheduler都没有无法迫使continue委托返回到原来的上下文或者你使用”await task.ConfigureAwait(false)代替”await task;”然后continue委托不会迫使返回到原来上下文并且将允许在系统认为合适的地方继续运行。这通常意味着要么以同步方式运行continue委托无论等待的task在哪完成要么使用ThreadPool中的线程运行continue委托。 7.         在控制台程序中能使用”await”吗 当然能。但你不能在Main()方法中使用”await”因为入口点不能被标记为”async”。相反你能在控制台应用程序的其他方法中使用”await”。如果你在Main()中调用这些方法你可以同步等待(而不是异步等待)他们的完成。Eg 你还可以使用自定义的SynchronizationContext或TaskScheduler来实现相似的功能更多信息请看 1)         Await, SynchronizationContext, and Console Apps: Part 1 2)         Await, SynchronizationContext, and Console Apps: Part 2 3)         Await, SynchronizationContext, and Console Apps: Part 3 8.         “await”能和异步编程模型模式(APM)或基于事件的异步编程模式(EAP)一起使用吗 当然能你可以为你的异步操作实现一个自定义的”awaitable”或者将你现有的异步操作转化为现有的”awaitable”像task或taskTResult。示例如下 1)         Tasks and the APM Pattern 2)         Tasks and the Event-based Asynchronous Pattern 3)         Advanced APM Consumption in Async Methods 4)         Implementing a SynchronizationContext.SendAsync method 5)         Awaiting Socket Operations 6)         await anything 7)         The Nature of TaskCompletionSourceTResult 9.         编译器对async/await生成的代码是否能高效异步执行 大多数情况下是的。因为大量的生成代码已经被编译器所优化并且.NET Framework也为生成代码建立依赖关系。要了解更多信息包括使用async/await的最小化开销的最佳实践等。请看 1)         .NET4.5对TPL的性能提升 2)         2012年MVP峰会上的“The Zen of Async” 3)         《了解 Async 和 Await 的成本》 原文http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspx 作者Stephen Toub - MSFT 另外稍作改动参考文献C# Async Tips and Tricks Part 2 : Async Void
http://www.pierceye.com/news/553872/

相关文章:

  • 三合一网站一般多少钱浙江省和住房建设厅网站
  • 网站开发背景知识论文网页设计表格
  • 广州优秀网站建设怎么寻找国外客户资源
  • 松江新城投资建设集团有限公司网站华能电子商务平台
  • 网站建设设计制作公司微网站微商城
  • 长宁企业网站建设个人做外贸怎么做
  • 饲料 东莞网站建设免费推广app
  • 手机平台网站开发品牌网站设计首选
  • 哪些网站可以做调查赚钱图片生成软件
  • 网站空间的管理wordpress vip system
  • 新思维网站北京住房建设部网站首页
  • 温州网站制作套餐麒麟网站建设
  • 淘宝接单做网站wordpress能做企业网站吗
  • 网站建设运营公众号运营合同app网站开发书籍下载
  • 网站seo流程网站开发开账务处理
  • 婚介网站方案长沙网络公司电话
  • 自助网站搭建系统做网站接电话一般要会什么
  • 雷州网站建设公司网站建设与管理说课ppt
  • 问答类网站怎么做wordpress 调取页面缩略图
  • 做电影资源网站手机版wordpress实例配置
  • 广西网站建设方案品牌官网方案
  • 游戏工作室网络组建方案seo81
  • 搭建个人网站的步骤温州专业微网站制作价格
  • 网站怎么做充值系统php图书管理系统网站开发
  • 多商家网站建设自助建站系统源码 资源网
  • 广州番禺网站制作公司哪家好文章网站建设
  • 漯河网站建设e辽宁身营商环境建设局网站
  • 营销网站建设套餐企业信息公示管理系统
  • 网站布局设计排版网站外部链接做多少合适呢
  • 成品网站 源码1688上海网站建设 找德华专业