写在前方

写在头里

  在学异步,有位园友推荐了《async in
C#5.0》,没找到汉语版,恰巧也想增强下英文,用自己迟钝的英文翻译一些最紧要的局地,纯属娱乐,简单分享,保持学习,谨记谦虚。

  在学异步,有位园友推荐了《async in
C#5.0》,没找到汉语版,恰巧也想进步下英文,用自我戆直的英文翻译一些重点的片段,纯属娱乐,不难分享,保持学习,谨记谦虚。

  倘诺您觉得那件事情没意义翻译的又差,尽情的踩吧。假设您以为值得鼓励,感谢留下你的赞,愿爱技术的园友们在此后每一趟应该可以突破的时候,不选用知难而退。在每一趟应该单独思想的时候,不接纳与世浮沉,应该大力的时候,不接纳尽量,不辜负每一秒存在的含义。

  如若你觉得那件事情没意义翻译的又差,尽情的踩吧。固然你以为值得鼓励,感谢留下您的赞,愿爱技术的园友们在将来每五回应该可以突破的时候,不选用知难而退。在每五遍应该单独思考的时候,不选取与世浮沉,应该努力的时候,不接纳尽量,不辜负每一秒存在的意思。

  
转发和爬虫请声明原文链接http://www.cnblogs.com/tdws/p/5628538.html,博客园
蜗牛 2016年6月27日。

  
转发和爬虫请注明原文链接http://www.cnblogs.com/tdws/p/5628538.html,博客园
蜗牛 2016年6月27日。

目录

目录

第01章 异步编程介绍

第01章 异步编程介绍

第02章 为啥选择异步编程

第02章 为啥拔取异步编程

第03章 手动编写异步代码

第03章 手动编写异步代码

    .NET中的一些异步形式
    最简便易行的异步情势
    关于Task的介绍
    手动编写异步代码的问题
    应用手写异步代码转换示例(第二章结尾一个演示)

    .NET中的一些异步形式
    最简便易行的异步形式
    关于Task的介绍
    手动编写异步代码的标题
    应用手写异步代码转换示例(第二章结尾一个示范)

第04章 编写Async方法

第04章 编写Async方法

第05章 Await究竟做了如何

第05章 Await究竟做了什么

第06章
以Task为底蕴的异步情势

第06章
以Task为底蕴的异步形式

第07章 异步代码的一对工具

第07章 异步代码的有的工具

第08章 哪个线程在运转你的代码

第08章 哪个线程在运作你的代码

第09章 异步编程中的分外

第09章 异步编程中的格外

第10章 并行使用异步编程

第10章 并行使用异步编程

第11章 单元测试你的异步代码

第11章 单元测试你的异步代码

第12章 ASP.NET应用中的异步编程

第12章 ASP.NET应用中的异步编程

第13章 WinRT应用中的异步编程

第13章 WinRT应用中的异步编程

第14章 编译器在尾部为您的异步做了怎么

第14章 编译器在底层为您的异步做了哪些

第15章 异步代码的性质

第15章 异步代码的特性

手动编写异步代码

手动编写异步代码

  在本章,大家将会谈谈一些关于不使用C#5.0主要字async的异步编程。这种办法即便早已是过去的技巧,也许你不会再采纳,但那对于你通晓异步编程表象背后爆发了怎么事情是很要紧的。也因为那或多或少,我将会快速的叙述示例,仅仅爱抚揭穿出对您了解有救助的地方。

  在本章,我们将会谈谈一些有关不使用C#5.0重视字async的异步编程。那种艺术固然已经是过去的技能,也许你不会再利用,但那对于你知道异步编程表象背后爆发了何等工作是很关键的。也因为那点,我将会快捷的描述示例,仅仅重视揭发出对你知道有帮带的地方。

 

 

.NET中的一些异步形式

.NET中的一些异步情势

  正如本人事先涉嫌的,Silverlight只提供了像web访问的异步版本API。那里有一个事例,你可以下载一个网页,并出示它:

  正如我事先涉嫌的,Silverlight只提供了像web访问的异步版本API。那里有一个例子,你可以下载一个网页,并出示它:

private void DumpWebPage(Uri uri)
{
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted += OnDownloadStringCompleted;
webClient.DownloadStringAsync(uri);
}
private void OnDownloadStringCompleted(object sender,
DownloadStringCompletedEventArgs eventArgs)
{
m_TextBlock.Text = eventArgs.Result;
}
private void DumpWebPage(Uri uri)
{
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted += OnDownloadStringCompleted;
webClient.DownloadStringAsync(uri);
}
private void OnDownloadStringCompleted(object sender,
DownloadStringCompletedEventArgs eventArgs)
{
m_TextBlock.Text = eventArgs.Result;
}

  那种API是依据事件的异步情势(EAP)。那几个想法是想替代单线程方法去下载网页,即阻塞型代码会一向等到下载甘休再调用一个情势或接触一个风云。这些办法看起来和一起代码一样,除了无重临类型。这一个事件也有一个专门的eventArgs类型,它涵盖值检索。

  那种API是按照事件的异步格局(EAP)。这些想法是想替代单线程方法去下载网页,即阻塞型代码会一贯等到下载截至再调用一个格局或接触一个轩然大波。这一个主意看起来和联合代码一样,除了无重临类型。那么些事件也有一个特地的eventArgs类型,它含有值检索。

  大家在调用那些点子前注册了事件。该方法即刻重返,当然那是因为它是异步代码。然后在未来的某个时刻触发。那种情势显明很复杂,不仅仅是因为您要将它分为像例子一样的四个主意。最要害的是,你注册了一个年华增多了复杂。如若说我还要用同样的WebClient实例处理其余要求,那么你恐怕不希望以此小时如故被增大着还要再度实施三回。

  大家在调用那个点子前注册了风浪。该方法马上回去,当然那是因为它是异步代码。然后在以后的某部时刻触发。那种格局分明很复杂,不仅仅是因为您要将它分成像例子一样的三个办法。最重大的是,你注册了一个日子增多了复杂。假诺说我还要用同样的WebClient实例处理其余需要,那么您恐怕不愿意那几个时间如故被增大着还要再一次实施一回。

  在.NET功效中另一个异步方式设计IAsyncResult接口。其中一个事例就是DNS查找主机名的IP地址,BeginGetHoseAddress。那种设计要求四个办法,一个是初阶履行的BeginMethodName,另一个是推行甘休EndMethodName,即你的回调方法。

  在.NET功用中另一个异步格局设计IAsyncResult接口。其中一个例子就是DNS查找主机名的IP地址,BeginGetHoseAddress。这种布置必要多个措施,一个是早先推行的BeginMethodName,另一个是履行截至EndMethodName,即你的回调方法。

private void LookupHostName()
{
object unrelatedObject = "hello";
Dns.BeginGetHostAddresses("oreilly.com", OnHostNameResolved, unrelatedObject);
}
private void OnHostNameResolved(IAsyncResult ar)
{
object unrelatedObject = ar.AsyncState;
IPAddress[] addresses = Dns.EndGetHostAddresses(ar);
// Do something with addresses
...
}
private void LookupHostName()
{
object unrelatedObject = "hello";
Dns.BeginGetHostAddresses("oreilly.com", OnHostNameResolved, unrelatedObject);
}
private void OnHostNameResolved(IAsyncResult ar)
{
object unrelatedObject = ar.AsyncState;
IPAddress[] addresses = Dns.EndGetHostAddresses(ar);
// Do something with addresses
...
}

  至少那种办法不会见临残留注册事件的震慑,但是那也至极的对API增添了复杂。有多少个法子而不是一个,我认为很不自然。

  至少那种办法不会碰到残留注册事件的影响,然则那也相当的对API增加了复杂。有四个办法而不是一个,我觉得很不自然。

  这三种异步情势都急需你分为四个点子来书写。IAsyncResult情势要你从首个章程中向第四个章程传递某些参数,如同本人传递了string类型的”hello”。但是这种格局很复杂,尽管你不要求以此参数,仍旧只可以传递它,并且迫使你转移为object类型。

  那两种异步情势都亟待您分为五个办法来书写。IAsyncResult形式要你从第二个主意中向第三个主意传递某些参数,如同我传递了string类型的”hello”。不过那种办法很复杂,即便你不须要这一个参数,依然不得不传递它,并且迫使你转移为object类型。

 

 

最简易的异步形式

最简单易行的异步形式

  可以说下边那段代码拥有异步行为,尽管不选择async关键字,也不用向方法传递委托:

  可以说上边那段代码拥有异步行为,即便不使用async关键字,也不用向方法传递委托:

void GetHostAddress(string hostName, Action<IPAddress> callback)
void GetHostAddress(string hostName, Action<IPAddress> callback)

  我意识那种方法比其余方法越来越易用。

  我发现那种格局比其余方法尤其易用。

private void LookupHostName()
{
GetHostAddress("oreilly.com", OnHostNameResolved);
}
private void OnHostNameResolved(IPAddress address)
{
// Do something with address
...
}
private void LookupHostName()
{
GetHostAddress("oreilly.com", OnHostNameResolved);
}
private void OnHostNameResolved(IPAddress address)
{
// Do something with address
...
}

  分化于八个法子的形式,像自家原先提到的,使用异步方法或者用lambda表明式做回调。它具备首要的益处就是可以在首先个措施中走访变量。

  不相同于三个主意的格局,像自家原先提到的,使用异步方法或者用lambda表明式做回调。它兼具主要的便宜就是可以在首先个方法中访问变量。

private void LookupHostName()
{
int aUsefulVariable = 3;
GetHostAddress("oreilly.com", address =>
{
// Do something with address and aUsefulVariable
...
});
}
private void LookupHostName()
{
int aUsefulVariable = 3;
GetHostAddress("oreilly.com", address =>
{
// Do something with address and aUsefulVariable
...
});
}

  这一个Lambda有几许麻烦阅读,并且普通假使您使用多重的异步编程,你将索要过Dora姆da表明式相互嵌套,你的代码将会很快变得长短不一和不便处理。

  这些拉姆da有少数不便阅读,并且普通假设您拔取多重的异步编程,你将须求广大拉姆da表明式相互嵌套,你的代码将会快速变得参差不齐和不便处理。

  那种简易方法的老毛病在于他们不再对调用者抛出更加。在此前.NET异步编程中,调用EndMethodName或者取得Result属性时,将会重新抛出相当,所以在代码中大家可以对应的处理至极。相反,他们也许在某个错误地点停下或者根本不去处理。

  那种简单方法的短处在于他们不再对调用者抛出极度。在以前.NET异步编程中,调用EndMethodName或者取得Result属性时,将会重新抛出越发,所以在代码中大家得以对应的拍卖相当。相反,他们唯恐在某个错误地点停下或者根本不去处理。

 

 

关于Task的介绍

关于Task的介绍

  义务并行实在.NET
Framework4.0版本中推出的。其最重大的地点是Task类,即表示一个正在实施的操作。
泛型版本的Task<T>, 当操作已毕时回来类型为T的值。

  职责并行实在.NET
Framework4.0版本中出产的。其最重视的地点是Task类,即表示一个正值实践的操作。
泛型版本的Task<T>, 当操作达成时回来类型为T的值。

   在C#5.0
async作用上大家多量的施用了Task,大家将会稍后切磋。但是即使没有async,你照旧可以接纳Task,越发是利用Task<T>来异步编程。那样做就行,你起头一个回到Task<T>的操作,然后选拔ContinueWith方法注册你的回掉方法。

   在C#5.0
async作用上我们大量的施用了Task,大家将会稍后商量。然则即使没有async,你如故可以选拔Task,更加是运用Task<T>来异步编程。那样做就行,你起来一个再次来到Task<T>的操作,然后使用ContinueWith方法注册你的回掉方法。

private void LookupHostName()
{
Task<IPAddress[]> ipAddressesPromise = Dns.GetHostAddressesAsync("oreilly.com");
ipAddressesPromise.ContinueWith(_ =>
{
IPAddress[] ipAddresses = ipAddressesPromise.Result;
// Do something with address
...
});
}
private void LookupHostName()
{
Task<IPAddress[]> ipAddressesPromise = Dns.GetHostAddressesAsync("oreilly.com");
ipAddressesPromise.ContinueWith(_ =>
{
IPAddress[] ipAddresses = ipAddressesPromise.Result;
// Do something with address
...
});
}

  Task的长处就如这一个DNS只须求一个主意,使API越发整洁。所有调用异步行为相关的逻辑都可在Task类当中,所以它不需求在每一个办法里都进展复制。这几个逻辑可以做过多重大的事儿,比如拍卖格外和一块上下文(SynchronizationContexts)。那几个,大家将会在第八章啄磨,对于在一个一定线程上推行callback很有用处(比如UI线程)。

  Task的亮点就像是这么些DNS只需求一个办法,使API越发清洁。所有调用异步行为相关的逻辑都可在Task类当中,所以它不须要在每一个形式里都开展复制。那个逻辑可以做过多重中之重的事宜,比如拍卖至极和联合上下文(SynchronizationContexts)。这些,我们将会在第八章琢磨,对于在一个一定线程上实施callback很有用处(比如UI线程)。

  最首要的是,Task给我们提供一种选用异步的相对抽象的操作形式。大家得以拔取那种组合型去编写大家的工具,即在广大索要利用Task的事态下提须要一些灵光的表现。大家将会看出许多相关的工具组件(utilities)在第七章当中。

  最要害的是,Task给我们提供一种选择异步的相对抽象的操作办法。我们得以行使那种组合型去编写大家的工具,即在许多索要利用Task的境况下提必要一些得力的行事。大家将会师到众多有关的工具组件(utilities)在第七章当中。

 

 

手动编写异步代码的题材

手动编写异步代码的难点

  
正如我们见到的,大家有不可胜言办法来兑现异步编程。有局地措施比其他措施整洁易懂易用,但是也期待您曾经看到他们共有的败笔。你打算写的次第不得不分为几个艺术:实际的点子和回调方法。还有使用异步方法或嵌套多次lambda表明式作为回调,使你的代码一环套一环难以了解。

  
正如我们看到的,我们有许多艺术来兑现异步编程。有一部分格局比其余措施整洁易懂易用,可是也可望您曾经见到他们共有的毛病。你打算写的顺序不得不分为三个法子:实际的法子和回调方法。还有使用异步方法或嵌套数次lambda表明式作为回调,使您的代码一环套一环难以掌握。

  实际上那里还有另一个题材。大家早已说过调用三遍异步方法的气象,可是当你须求三个异步时会发生什么吧?更不好的是,若是弄须要在循环中调用异步又会发出怎么样吗?你为一个办法是运用递归方法,那又比平时的巡回难以阅读多了。

  实际上这里还有另一个难点。我们早就说过调用一次异步方法的事态,可是当您须求几个异步时会发生哪些吧?更不好的是,如若弄须求在循环中调用异步又会发出怎么着吗?你为一个措施是利用递归方法,那又比平日的大循环难以阅读多了。

private void LookupHostNames(string[] hostNames)
{
LookUpHostNamesHelper(hostNames, 0);
}

private static void LookUpHostNamesHelper(string[] hostNames, int i)
{
Task<IPAddress[]> ipAddressesPromise = Dns.GetHostAddressesAsync(hostNames[i]);
ipAddressesPromise.ContinueWith(_ =>
{
IPAddress[] ipAddresses = ipAddressesPromise.Result;
// Do something with address
...
if (i + 1 < hostNames.Length)
{
LookUpHostNamesHelper(hostNames, i + 1);
}
});
}
private void LookupHostNames(string[] hostNames)
{
LookUpHostNamesHelper(hostNames, 0);
}

private static void LookUpHostNamesHelper(string[] hostNames, int i)
{
Task<IPAddress[]> ipAddressesPromise = Dns.GetHostAddressesAsync(hostNames[i]);
ipAddressesPromise.ContinueWith(_ =>
{
IPAddress[] ipAddresses = ipAddressesPromise.Result;
// Do something with address
...
if (i + 1 < hostNames.Length)
{
LookUpHostNamesHelper(hostNames, i + 1);
}
});
}

  哇!

  哇!

  在这个异步编程方式中,引发的另一个题材就是急需消耗大批量代码。要是您写一些异步代码,期望在任啥地点方拔取,你不得不提供API,假诺API混乱或者忘记当时的初衷不能精晓的话,将会一箭双雕。异步代码是会“传染”的,由此不但你需求异步API,还影响调用者和调用者的调用者,知道一切程序乱成一团。

  在那个异步编程格局中,引发的另一个标题就是内需消耗大量代码。即使你写一些异步代码,期望在其余地点选拔,你不得不提供API,若是API混乱或者忘记当时的初衷不可以掌握的话,将会一举两得。异步代码是会“传染”的,由此不但你须要异步API,还影响调用者和调用者的调用者,知道整个程序乱成一团。

 

 

应用手写异步代码转换示例(第二章结尾一个演示)

动用手写异步代码转换示例(第二章结尾一个示范)

  再来谈谈第二章最终一个示范,大家谈论了一个会因从网站下载icons,造成UI线程阻塞,并促成出现应用程序未响应的WPF
UI app。现在我们将会合到,将它转化成手写的异步代码。

  再来谈谈第二章最后一个演示,大家谈论了一个会因从网站下载icons,造成UI线程阻塞,并致使出现应用程序未响应的WPF
UI app。现在大家将见面到,将它转载成手写的异步代码。

  第首先要做的就是找到一个异步API的本子,我用(WebClient。下载文件)。正如我们已经看到的,WebClient方法运用基于事件的异步方式(EAP),所以大家可以在先河下载以前注册一个轩然大波视作回调方法。

  第首先要做的就是找到一个异步API的本子,我用(WebClient。下载文件)。正如大家早已看到的,WebClient方法运用基于事件的异步方式(EAP),所以大家能够在上马下载此前注册一个事变视作回调方法。

private void AddAFavicon(string domain)
{
WebClient webClient = new WebClient();
webClient.DownloadDataCompleted += OnWebClientOnDownloadDataCompleted;
webClient.DownloadDataAsync(new Uri("http://" + domain + "/favicon.ico"));
}
private void OnWebClientOnDownloadDataCompleted(object sender,
DownloadDataCompletedEventArgs args)
{
Image imageControl = MakeImageControl(args.Result);
m_WrapPanel.Children.Add(imageControl);
}
private void AddAFavicon(string domain)
{
WebClient webClient = new WebClient();
webClient.DownloadDataCompleted += OnWebClientOnDownloadDataCompleted;
webClient.DownloadDataAsync(new Uri("http://" + domain + "/favicon.ico"));
}
private void OnWebClientOnDownloadDataCompleted(object sender,
DownloadDataCompletedEventArgs args)
{
Image imageControl = MakeImageControl(args.Result);
m_WrapPanel.Children.Add(imageControl);
}

  当然,我们的真正属于一起的逻辑要被分为五个办法。我不喜欢使用Lambda来代替刚才的EAP,因为lambda会油可是生在真的初阶下载前,我觉得那是不足读的。

  当然,大家的着实属于一起的逻辑要被分成多少个办法。我不爱好使用拉姆da来取代刚才的EAP,因为lambda会现出在真正伊始下载前,我觉着这是不足读的。

  这么些版本的言传身教也足以在线(https://bitbucket.org/alexdavies74/faviconbrowser)找到,(//译者注释:不运行此程序也没关系,主要是体会下思路就好)在manual分支。如果你运行它,不进界面可相应,图标也会逐一出现。正因此,我们也引入了一个bug,现在由于所有下载操作同时开始,icons的排序由其下载先后决定,而不是由我的先后请求来决定。如果你想检验自己是否理解手动编写异步代码,我建议你尝试着解决此bug。在orderedManual分支下(上面列出的站点下)提供了一个解决方案。其他更有效的解决方案也是有可能的。

  那个版本的示范也足以在线(https://bitbucket.org/alexdavies74/faviconbrowser)找到,(//译者注释:不运行此程序也没关系,主要是体会下思路就好)在manual分支。如果你运行它,不进界面可相应,图标也会逐一出现。正因此,我们也引入了一个bug,现在由于所有下载操作同时开始,icons的排序由其下载先后决定,而不是由我的先后请求来决定。如果你想检验自己是否理解手动编写异步代码,我建议你尝试着解决此bug。在orderedManual分支下(上面列出的站点下)提供了一个解决方案。其他更有效的解决方案也是有可能的。

写在背后

写在末端

27号入职,花了三日的业余时间,坎坎坷坷的翻译了第三章。若是您对您有点许益处,不要吝啬你的赞,给个鼓励。不规范和须求补给的地点,也请前辈们不吝赐教,我将谦虚改正。下一章将会介绍 “编写Async方法

27号入职,花了四日的业余时间,坎坎坷坷的翻译了第三章。假诺你对你稍微许益处,不要吝啬你的赞,给个鼓励。不精确和内需补充的地点,也请前辈们不吝赐教,我将谦虚改进。下一章将会介绍 “编写Async方法

相关文章