C# 5.0 两个新关键字 async await 在Silverlight中的应用

去年8月发布的最新版 .NET Framework 4.5 支持 C# 5.0中两个新的关键字:async, await

这两个关键字能极大的简化传统的C# 异步函数代码:

我们先来看看在Silverlight5.0 .NET 4.0 环境下使用 HttpWebRequest 类来发送POST请求的方法:

 

var req = (HttpWebRequest)WebRequest.Create("http://192.168.100.117:6080/arcgis/admin/generateToken");
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.BeginGetRequestStream(new AsyncCallback(RequestReady), req);


这段代码首先创建了一个HttpWebRequest对象,然后通过异步的  BeginGetRequestStream 方法来获取用来写入POST 数据的流(通过回调函数RequestReady的传参)

然后在回调函数中,我们获取了用来写数据的 Stream对象,往里面写入数据后,又发起一个异步请求:BeginGetResponse 来获取返回结果

private void RequestReady(IAsyncResult ar)
{
HttpWebRequest request = (HttpWebRequest)ar.AsyncState;
System.IO.Stream stream = request.EndGetRequestStream(ar);
StreamWriter writer = new StreamWriter(stream);
writer.WriteLine("username=id");
writer.WriteLine("&client=IP");
writer.WriteLine("&IP=192.168.100.117");
writer.WriteLine("&password=pwd");
writer.Flush();
writer.Close();
request.BeginGetResponse(new AsyncCallback(ResponseReady), request);
}


 

 这样我们最终通过回调函数ResponseReady 获得了最终想要的结果:

private void ResponseReady(IAsyncResult asyncResult)
{
HttpWebRequest request = asyncResult.AsyncState as HttpWebRequest;
try
{
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);
this.Dispatcher.BeginInvoke(delegate()
{
System.IO.Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
token = reader.ReadToEnd();					
});

}
catch (WebException webException)
{
MessageBox.Show(webException.Response.ToString());
}
}

 

若有了async 和 await 这两个关键字的支持,我们的异步请求代码就会变的非常简单:

在使用这两个关键字之前,我们需要了解的是 对于异步代码的支持是在编译阶段完成的,这也意味着这我们必须使用最新的编译器,才能实现对C# 5.0 这两个关键字的支持,VS2010是不支持C# 5.0的。对于编译器为了实现async 和 await,在底层做了大量的工作,具体可以参考这里

值得庆幸的是,在VS 2012 环境下,微软为我们提供了 针对.NET Framework 4.0 ,Silverlight 5.0 平台的常用异步请求扩展包,我们可以使用VS 2012自带的扩展库管理工具Nugget来获得它。


在Search Online搜索框中输入 AsyncTargetingPack, 就可以找到该扩展包了:


在安装了扩展包后,可以注意到在我们的项目中添加了一个 Microsoft.CompilerServices.AsyncTargetingPack.Silverlight5.dll 的引用

在对象查看器中,我们可以看到这个类库对很多常用的IO方法 以及Web方法都做了扩展:



 有了这个extension,我们上文中的POST请求代码就可以简化成如下的样子:

var req = (HttpWebRequest)WebRequest.Create(string.Format("http://{0}:{1}/arcgis/admin/generateToken", serverName, portNumber));	req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
Stream x = await req.GetRequestStreamAsync();
StreamWriter writer = new StreamWriter(x);
writer.WriteLine(string.Format("username={0}", username));                   //user with administrator priviliage
writer.WriteLine("&client=requestip");
writer.WriteLine(string.Format("&password={0}", password));              //use your own password
writer.Flush();
writer.Close();
WebResponse resp = await req.GetResponseAsync();
Stream x1 = resp.GetResponseStream();
StreamReader reader = new StreamReader(x1);
return reader.ReadToEnd();

添加了AsyncTargetingPack后,HttpWebRequest类增加获取请求流的异步方法:


上图中我们可以注意到这个函数是通过 extension实现的,且awaitable,它返回的是一个Stream对象(异步返回结果都需要用Task封装),这样我们只需要在调用这个函数时在前面加上await就可以让代码执行等待异步的返回结果,即在获取了结果后再执行下一行代码,这样的代码十分符合人类的逻辑思维。同理,获取Web请求返回结果也可以使用await来暂停。

需要注意的是,若要支持await操作符,我们必须将包含await的函数声明为async的方法,即假设上文的代码是运行在一个Button的Click Event Handler中,那么我们必须将这个 Event Handler声明为 async的,即:

private async void Btn_Click(object sender, RoutedEventArgs e)


await async 的意义不仅仅是简化代码逻辑,最重要的是,有了它们的支持,可以实现并发异步请求(Concurrent asynchronous calls)。

例如一个常见的需求,我们使用WebClient通过一个循环来Download 不同Uri的数据,使用以下代码,在Visual Studio中是不支持的(runtime error: NotSupportedException was unhandled by user code. "Request does not support concurrent I/O operations."):




如果有了await的支持,我们就可以轻易实现循环并发异步请求:

foreach (string folderName in ss.folders)
{
string subFolderServiceJson = await wc.DownloadStringTaskAsync(string.Format("http://{0}:{1}/arcgis/admin/services/{2}?f=json&token={3}", server_tbx.Text, port_number_tbx.Text, folderName, s));
// do sth. with subFolderServiceJson 
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值