异步编程系列第03章 自己写异步代码

作者:澳门唯一金莎娱乐

写在前头

异步编程系列第03章 自己写异步代码。  在学异步,有位园友推荐了《async in C#5.0》,没找到普通话版,凑巧也想加强下法语,用本人古板的土耳其共和国(The Republic of Turkey)语翻译一些重视的有个别,纯属娱乐,简单分享,保持学习,谨记谦和。

  假若您认为这事儿没意义翻译的又差,尽情的踩吧。倘让你以为值得激励,感激留下您的赞,愿爱本领的园友们在今后每贰遍应该能够突破的时候,不接纳急流勇退。在每叁遍应该单独思量的时候,不选用与世起落,应该奋力的时候,不选拔尽量,不负每风流洒脱秒存在的意义。

   转发和爬虫请注解原著链接,博客园 蜗牛 2016年6月27日。

目录

异步编程系列第03章 自己写异步代码。第01章 异步编制程序介绍

第02章 为什么使用异步编制程序

异步编程系列第03章 自己写异步代码。第03章 手动编写异步代码

    .NET中的一些异步格局
    最简易的异步情势
    关于Task的介绍
    手动编写异步代码的题目
    行使手写异步代码转变示例(第二章结尾两个示范)

第04章 编写Async方法

第05章 Await终究做了何等

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

第07章 异步代码的生机勃勃对工具

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

第09章 异步编制程序中的非凡

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

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

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

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

第14章 编写翻译器在底层为您的异步做了怎么样

第15章 异步代码的性质

手动编写异步代码

  在本章,大家将会切磋一些有关不使用C#5.0主要字async的异步编制程序。这种方法即使曾经是病故的才能,可能你不会再选择,但那对于你知道异步编制程序表象背后爆发了哪些职业是很关键的。也因为那点,我将会快速的叙说示例,仅仅器重揭露出对你精通有助于的地点。

 

.NET中的一些异步格局

  正如本身事先涉嫌的,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;
}

  这种API是借助事件的异步形式(EAP)。这几个主张是想替代单线程方法去下载网页,即阻塞型代码会平素等到下载结束再调用三个办法或接触贰个事变。那么些艺术看起来和一块代码同样,除了无重返类型。这么些事件也可能有多少个特地的eventArgs类型,它满含值检索。

  大家在调用这些法子前注册了风浪。该办法马上回去,当然那是因为它是异步代码。然后在以后的某部时刻触发。这种形式分明很复杂,不止是因为你要将它分为像例子同样的七个情势。最关键的是,你注册了多个时间增添了复杂。假诺说作者还要用平等的WebClient实例管理其他要求,那么你大概不希望以那时刻依然被增大着还要再度实践一次。

  在.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
...
}

  起码这种艺术不会蒙受残存注册事件的熏陶,但是那也格外的对API扩大了复杂。有多少个章程并不是五个,小编感觉特别不自然。

  那二种异步情势都必要你分为四个主意来书写。IAsyncResult形式要你从第三个章程中向第3个章程传递有个别参数,就像笔者传递了string类型的"hello"。然而这种办法很复杂,即便你没有需求以此参数,照旧一定要传递它,何况迫让你转移为object类型。

 

最简便易行的异步格局

  可以说上面这段代码具备异步行为,就算不利用async关键字,也不用向方法传递委托:

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

  小编发觉这种方法比别的方法尤其易用。

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

  不一致于多个艺术的情势,像小编原先提到的,使用异步方法也许用lambda表明式做回调。它有重视要的好处便是能够在率先个办法中做客变量。

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

  这些Lambda有好几麻烦阅读,何况普通假如您利用多种的异步编制程序,你将急需多Dora姆da表明式相互嵌套,你的代码将会快捷变得犬牙相制和麻烦管理。

  这种轻巧方法的弱点在于他们不再对调用者抛出卓殊。在在此以前.NET异步编制程序中,调用EndMethodName恐怕取得Result属性时,将会再一次抛出特别,所以在代码中大家得以对应的管理极其。相反,他们也许在某些错误地点停下恐怕根本不去管理。

 

关于Task的介绍

  职务并行实在.NET Framework4.0本子中生产的。其最首要的位置是Task类,即意味着一个正值实行的操作。 泛型版本的Task<T>, 当操作达成时再次回到类型为T的值。

   在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
...
});
}

  Task的优点好似那个DNS只需求八个主意,使API特别卫生。全体调用异步行为有关的逻辑都可在Task类当中,所以它没有必要在每叁个方式里都开展复制。那一个逻辑能够做过多至关心珍爱要的事情,比方拍卖特别和一同上下文(SynchronizationContexts)。这一个,大家将会在第八章商讨,对于在一个特定线程上施行callback很有用处(比如UI线程)。

  最珍视的是,Task给我们提供风度翩翩种选取异步的相对抽象的操作方法。大家能够采纳这种组合型去编写大家的工具,即在重重亟需采纳Task的景色下提要求一些管用的表现。大家将造访到众多有关的工具组件(utilities)在第七章此中。

 

手动编写异步代码的难点

   正如大家看出的,大家有无数主意来落实异步编制程序。有生机勃勃部分措施比别的措施整洁易懂易用,不过也盼望你早就见到他们共有的顽固的病魔。你准备写的次序必须要分为七个点子:实际的主意和回调方法。还应该有使用异步方法或嵌套多次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);
}
});
}

  哇!

  在此些异步编制程序情势中,引发的另四个主题素材就是内需消耗大量代码。尽管您写一些异步代码,期待在别的地点使用,你必须要提供API,要是API混乱或然忘记那时的初志不能够领悟的话,将会一本万利。异步代码是会“传染”的,因而不但你要求异步API,还影响调用者和调用者的调用者,知道整个程序乱作一团。

 

运用手写异步代码转变示例(第二章结尾贰个演示)

  再来谈谈第二章最终叁个演示,大家谈谈了三个会因从网址下载icons,产生UI线程阻塞,并导致现身应用程序未响应的WPF UI app。现在我们将会看出,将它转化成手写的异步代码。

  第首先要做的正是找到贰个异步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);
}

  当然,大家的确实属于一同的逻辑要被分为多个点子。笔者不希罕使用拉姆da来代替刚才的EAP,因为lambda会冒出在真的伊始下载前,小编认为这是不可读的。

  那个本子的亲自去做也能够在线(

写在后头

27号入职,花了30日的业余时间,风雨满城的翻译了第三章。假设您对你有个别许益处,不要吝啬你的赞,给个鼓劲。不确切和急需补充之处,也请前辈们不吝指教,小编将谦逊改进。下风流罗曼蒂克章将会介绍 “编写Async方法”

本文由金沙易记域名4166am发布,转载请注明来源

关键词: