我正忙着使用windows应用程序,当然它使用silverlight。这意味着调用任何when服务都必须异步完成,而且由于这对于防止等待资源时挂起整个应用程序的最佳实践来说都是很好的,所以我仍然停留在“同步思维”中.
因为我现在的看法是,您最终有两个需要处理一个函数的方法,例如:
1)实际调用webservice的方法:
public void myAsyncWebService(DownloadStringCompletedEventHandler callback)
{
//Url to webservice
string servletUrl = "https://deangrobler.com/someService/etc/etc"
//Calls Servlet
WebClient client = new WebClient();
client.DownloadStringCompleted += callback;
client.DownloadStringAsync(new Uri(servletUrl, UriKind.Absolute));
}
( 2)以及当数据最终返回时处理数据的方法:
private void serviceReturn(object sender, DownloadStringCompletedEventArgs e)
{
var jsonResponse = e.Result;
//and so on and so forth...
}
因此,不必只创建和调用一个方法,该方法转到webservice,获取返回的结果,然后按如下方式发送给我:
public string mySyncWebService(){
//Calls the webservice
// ...waits for return
//And returns result
}
我必须在一个类调用myAsyncWebService中,和在调用类中创建另一个方法来处理myAsyncWebService返回的结果。只是,在我看来,会造成混乱的代码。使用同步调用,您可以只调用一个方法并完成它。
我只是用错了异步调用吗?我的理解错了吗?我需要一些启发,我讨厌做这个杂乱无章的异步调用。这使得我的代码太复杂了,可读性只会转到.见鬼。
感谢任何人愿意改变我的想法!
发布于 2012-11-21 13:28:35
为了异步编程,你必须把你的思想倒转出来。我是凭经验说话的。:)
我只是用错了异步调用吗?我的理解错了吗?
不是的。异步代码很难编写(不要忘记错误处理),维护也非常困难。
这就是async
和await
被发明的原因。
如果您能够升级到VS2012,那么您可以使用Microsoft.Bcl.Async (目前处于测试版)编写如下代码:
string url1 = "https://deangrobler.com/someService/etc/etc";
string jsonResponse1 = await new WebClient().DownloadStringTaskAsync(url1);
string url2 = GetUriFromJson(jsonResponse1);
string jsonResponse2 = await new WebClient().DownloadStringTaskAsync(url2);
写起来很容易。易于维护。
发布于 2012-11-21 11:21:18
异步就像你打了电话,得到了答录机,如果你想要回电话,就留下你的电话号码。第一种方法是调用数据,第二种方法是为返回调用留下的“数字”。
发布于 2012-11-21 11:22:06
使用同步调用,您可以只调用一个方法并完成它。
当然,但是如果从UI线程执行此操作,则会阻塞整个UI。这在任何现代应用程序中都是不可接受的,特别是在浏览器或电话中运行的Silverlight应用程序中。当DNS查找超时时,手机不能响应30秒,这不是任何人想要使用的东西。
因此,在UI线程上,可能因为用户在UI中执行了一些操作,所以启动了一个异步调用。调用完成后,在后台线程上调用一个方法来处理调用的结果。此方法很可能使用异步调用的结果更新UI。
随着异步和等待在.NET 4.5中的引入,其中一些“拆分”代码可以简化。幸运的是,通过使用NuGet包Microsoft.Bcl.Async,Windows 7.5的测试版已经提供了异步和等待。
下面是一个很小(而且有点愚蠢)的示例,演示如何使用异步链接两个web服务调用。这适用于Windows4.5,但使用上面链接的.NET包,您应该能够在Windows 7.5上执行类似的操作。
async Task<String> GetCurrencyCode() {
using (var webClient = new WebClient()) {
var xml = await webClient.DownloadStringTaskAsync("http://freegeoip.net/xml/");
var xElement = XElement.Parse(xml);
var countryName = (String) xElement.Element("CountryName");
return await GetCurrencyCodeForCountry(countryName);
}
}
async Task<String> GetCurrencyCodeForCountry(String countryName) {
using (var webClient = new WebClient()) {
var outerXml = await webClient.DownloadStringTaskAsync("http://www.webservicex.net/country.asmx/GetCurrencyByCountry?CountryName=" + countryName);
var outerXElement = XElement.Parse(outerXml);
var innerXml = (String) outerXElement;
var innerXElement = XElement.Parse(innerXml);
var currencyCode = (String) innerXElement.Element("Table").Element("CurrencyCode");
return currencyCode;
}
}
但是,您仍然需要在UI线程和异步GetCurrencyCode
之间架设桥梁。不能在事件处理程序中等待,但可以对异步调用返回的任务使用Task.ContinueWith
:
void OnUserAction() {
GetCurrencyCode().ContinueWith(GetCurrencyCodeCallback);
}
void GetCurrencyCodeCallback(Task<String> task) {
if (!task.IsFaulted)
Console.WriteLine(task.Result);
else
Console.WriteLine(task.Exception);
}
https://stackoverflow.com/questions/13492027
复制相似问题