愿爱技术的园友们在其后每二次应该能够突破的时候,  假设您认为这件事儿没意义翻译的又差

写在前面

写在前头

  在学异步,有位园友推荐了《async in
C#伍.0》,没找到普通话版,恰巧也想增强下英文,用本身笨拙的英文翻译一些非同儿戏的局地,纯属娱乐,不难分享,保持学习,谨记谦虚。

  在学异步,有位园友推荐了《async in
C#伍.0》,没找到汉语版,恰巧也想升高下英文,用作者古板的英文翻译1些要害的片段,纯属娱乐,简单分享,保持学习,谨记谦虚。

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

  假设你觉得那件事儿没意义翻译的又差,尽情的踩吧。借使你以为值得鼓励,谢谢留下您的赞,愿爱技术的园友们在现在每2次应该能够突破的时候,不选用知难而退。在每一遍应该单独思索的时候,不选择随波逐流,应该奋力的时候,不采取尽量,不辜负每壹秒存在的意思。

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

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

目录

目录

第01章 异步编制程序介绍

第0一章 异步编程介绍

第02章 为何采用异步编制程序

第0二章 为何接纳异步编制程序

第0叁章 手动编写异步代码

第0三章 手动编写异步代码

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

    .NET中的1些异步方式
    最简便的异步方式
    关于Task的介绍
    手动编写异步代码的题材
    应用手写异步代码转换示例(第二章结尾三个演示)

第04章 编写Async方法

第04章 编写Async方法

第05章 Await终归做了什么样

第05章 Await究竟做了怎么

第0陆章
以Task为底蕴的异步格局

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

第0柒章 异步代码的1对工具

第07章 异步代码的部分工具

第0八章 哪个线程在运营你的代码

第0八章 哪个线程在运营你的代码

第0玖章 异步编制程序中的至极

第0九章 异步编制程序中的十分

第八章 并行使用异步编制程序

第八章 并行使用异步编制程序

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

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

第3二章 ASP.NET应用中的异步编制程序

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

第三三章 Win汉兰达T应用中的异步编制程序

第三叁章 Win纳瓦拉T应用中的异步编制程序

第一四章 编写翻译器在底层为你的异步做了哪些

第一四章 编写翻译器在头部为你的异步做了什么

第一5章 异步代码的习性

第15章 异步代码的质量

手动编写异步代码

手动编写异步代码

  在本章,大家将会谈论1些关于不使用C#5.0重中之重字async的异步编制程序。这种措施固然曾经是病故的技能,只怕你不会再使用,但那对于你精通异步编制程序表象背后产生了哪些工作是很重点的。也因为那或多或少,小编将会非常快的叙述示例,仅仅珍视揭露出对您精通有帮衬的地方。

  在本章,大家将会谈论壹些关于不使用C#5.0生死攸关字async的异步编制程序。这种办法纵然曾经是病故的技能,也许你不会再使用,但那对于你了解异步编制程序表象背后产生了怎么工作是很重大的。也因为那或多或少,作者将会快速的叙述示例,仅仅珍视揭发出对您领会有援救的位置。

 

 

.NET中的1些异步方式

.NET中的一些异步方式

  正如小编前面提到的,Silverlight只提供了像web访问的异步版本API。那里有3个事例,你能够下载2个网页,并体现它:

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

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)。那一个想法是想替代单线程方法去下载网页,即阻塞型代码会一向等到下载截止再调用三个措施或接触1个事变。那一个法子看起来和1道代码一样,除了无重回类型。这些事件也有三个特地的eventArgs类型,它含有值检索。

  大家在调用那么些办法前注册了风云。该方式马上回到,当然那是因为它是异步代码。然后在明日的有个别时刻触发。这种情势显然很复杂,不仅仅是因为你要将它分成像例子一样的七个章程。最器重的是,你注册了叁个年华增多了复杂。如果说笔者还要用同样的WebClient实例处理任何供给,那么你恐怕不期望那么些小时如故被增大着还要再度实施二次。

  我们在调用这么些点子前注册了轩然大波。该格局即刻回到,当然那是因为它是异步代码。然后在今后的某部时刻触发。那种方式分明很复杂,不仅仅是因为你要将它分为像例子一样的多个点子。最着重的是,你注册了贰个光阴扩充了复杂。假若说小编还要用同样的WebClient实例处理其余要求,那么你可能不指望以此时辰依旧被增大着还要再度实施2次。

  在.NET作用中另三个异步格局设计IAsyncResult接口。其中三个例证正是DNS查找主机名的IP地址,BeginGetHoseAddress。那种布置供给多个措施,1个是起先推行的BeginMethodName,另3个是实施甘休EndMethodName,即你的回调方法。

  在.NET功效中另四个异步情势设计IAsyncResult接口。个中1个例子就是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表达式做回调。它具有重要的益处就是能够在第3个章程中做客变量。

  不相同于多少个方法的方式,像笔者原先提到的,使用异步方法恐怕用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
...
});
}

  那么些兰姆da有有些难以阅读,并且普通假若你采用多重的异步编制程序,你将必要广大拉姆da表明式相互嵌套,你的代码将会急速变得错落有致和难以处理。

  这几个Lambda有一些不便阅读,并且普通即使你利用多重的异步编制程序,你将急需多多拉姆da表达式相互嵌套,你的代码将会非常的慢变得犬牙相错和不便处理。

  这种归纳方法的通病在于他们不再对调用者抛出特别。在之前.NET异步编制程序中,调用EndMethodName或许取得Result属性时,将会重新抛出卓殊,所以在代码中大家得以对应的处理相当。相反,他们大概在有些错误地点停下恐怕根本不去处理。

  那种简易方法的瑕疵在于他们不再对调用者抛出非凡。在在此以前.NET异步编制程序中,调用EndMethodName只怕取得Result属性时,将会再次抛出尤其,所以在代码中大家得以对应的拍卖万分。相反,他们或许在有个别错误地点停下恐怕根本不去处理。

 

 

关于Task的介绍

关于Task的介绍

  任务并行实在.NET
Framework肆.0版本中推出的。其最重大的地点是Task类,即意味着1个正值实施的操作。
泛型版本的Task<T>, 当操作达成时回来类型为T的值。

  任务并行实在.NET
Framework四.0版本中生产的。其最要害的地点是Task类,即意味着1个正值实践的操作。
泛型版本的Task<T>, 当操作完成时回来类型为T的值。

   在C#伍.0
async功用上我们多量的利用了Task,大家将会稍后研究。但是尽管未有async,你还是可以够运用Task,尤其是运用Task<T>来异步编制程序。那样做就行,你起来2个重临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只需求1个情势,使API尤其清新。全数调用异步行为相关的逻辑都可在Task类个中,所以它不需求在每多少个办法里都进展复制。这几个逻辑可以做过多主要的事体,比如拍卖分外和同步上下文(SynchronizationContexts)。那些,我们将会在第七章研讨,对于在1个一定线程上实施callback很有用处(比如UI线程)。

  Task的独到之处就如这一个DNS只需求3个办法,使API尤其整洁。全部调用异步行为相关的逻辑都可在Task类个中,所以它不须求在每二个措施里都进行复制。这几个逻辑能够做过多主要的事务,比如拍卖十分和一起上下文(SynchronizationContexts)。这几个,大家将会在第八章探讨,对于在三个一定线程上推行callback很有用处(比如UI线程)。

  最重大的是,Task给大家提供1种采用异步的相对抽象的操作方法。大家得以行使那种组合型去编写大家的工具,即在重重亟待动用Task的图景下提须要一些一蹴而就的一坐一起。我们将会晤到许多相关的工具组件(utilities)在第九歌个中。

  最关键的是,Task给大家提供1种选拔异步的争持抽象的操作办法。我们可以使用那种组合型去编写我们的工具,即在很多急需运用Task的场地下提供给1部分一蹴而就的一颦一笑。大家将会看到不少唇揭齿寒的工具组件(utilities)在第捌章在那之中。

 

 

手动编写异步代码的题材

手动编写异步代码的难题

  
正如我们看到的,大家有广大艺术来贯彻异步编程。有一部分方式比此外艺术整洁易懂易用,可是也指望你已经观看他们共有的毛病。你打算写的次第不得不分为多个主意:实际的法子和回调方法。还有使用异步方法或嵌套数十二遍lambda表达式作为回调,使您的代码一环套一环难以驾驭。

  
正如大家看来的,我们有好多艺术来实现异步编制程序。有部分方式比别的办法整洁易懂易用,然而也可望您曾经见到他们共有的瑕疵。你打算写的程序不得不分为多个方式:实际的点子和回调方法。还有使用异步方法或嵌套数十次lambda表明式作为回调,使你的代码一环套壹环难以明白。

  实际上那里还有另一个难题。我们早就说过调用3回异步方法的状态,但是当你要求八个异步时会爆发什么呢?更倒霉的是,假诺弄需求在循环中调用异步又会发生什么样啊?你为贰个措施是选用递归方法,这又比平常的循环难以阅读多了。

  实际上那里还有另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);
}
});
}
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);
}
});
}

  哇!

  哇!

  在这么些异步编制程序形式中,引发的另2个难点正是索要消耗多量代码。假诺你写1些异步代码,期望在此外省方选择,你不得不提供API,假诺API混乱恐怕忘记当时的初衷不能够明白的话,将会一箭双雕。异步代码是会“传染”的,由此不但你要求异步API,还影响调用者和调用者的调用者,知道整个程序乱成①团。

  在那个异步编程方式中,引发的另一个题材便是需求消耗大量代码。假使您写1些异步代码,期望在此外地点使用,你不得不提供API,要是API混乱只怕忘记当时的初衷不能够理解的话,将会一矢双穿。异步代码是会“传染”的,因而不但你要求异步API,还影响调用者和调用者的调用者,知道一切程序乱成壹团。

 

 

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

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

  再来谈谈第二章聊到底三个演示,我们谈论了四个会因从网站下载icons,造成UI线程阻塞,并造成出现应用程序未响应的WPF
UI app。未来我们将汇合到,将它转载成手写的异步代码。

  再来谈谈第二章末段3个演示,大家谈论了三个会因从网址下载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);
}

  当然,我们的真的属于一起的逻辑要被分成多个方法。作者不欣赏使用兰姆da来取代刚才的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分支下(上面列出的站点下)提供了一个解决方案。其他更有效的解决方案也是有可能的。

写在后边

写在后头

贰7号入职,花了三日的业余时间,坎坎坷坷的翻译了第一章。假若你对你有个别许益处,不要吝啬你的赞,给个鼓励。不确切和内需补充的地点,也请前辈们不吝赐教,笔者将谦虚更正。下1章将会介绍 “编写Async方法

二7号入职,花了四日的业余时间,坎坎坷坷的翻译了第二章。倘诺您对你稍微许益处,不要吝啬你的赞,给个鼓励。不纯粹和内需补给的地方,也请前辈们不吝赐教,小编将谦虚校对。下1章将会介绍 “编写Async方法

相关文章