首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从同步思维向非同步思维转变

从同步思维向非同步思维转变
EN

Stack Overflow用户
提问于 2012-11-21 11:12:38
回答 5查看 1K关注 0票数 0

我正忙着使用windows应用程序,当然它使用silverlight。这意味着调用任何when服务都必须异步完成,而且由于这对于防止等待资源时挂起整个应用程序的最佳实践来说都是很好的,所以我仍然停留在“同步思维”中.

因为我现在的看法是,您最终有两个需要处理一个函数的方法,例如:

1)实际调用webservice的方法:

代码语言:javascript
运行
复制
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)以及当数据最终返回时处理数据的方法:

代码语言:javascript
运行
复制
private void serviceReturn(object sender, DownloadStringCompletedEventArgs e)
{
    var jsonResponse = e.Result;
    //and so on and so forth...
}

因此,不必只创建和调用一个方法,该方法转到webservice,获取返回的结果,然后按如下方式发送给我:

代码语言:javascript
运行
复制
public string mySyncWebService(){
    //Calls the webservice
    // ...waits for return
    //And returns result
}

我必须在一个类调用myAsyncWebService中,在调用类中创建另一个方法来处理myAsyncWebService返回的结果。只是,在我看来,会造成混乱的代码。使用同步调用,您可以只调用一个方法并完成它。

我只是用错了异步调用吗?我的理解错了吗?我需要一些启发,我讨厌做这个杂乱无章的异步调用。这使得我的代码太复杂了,可读性只会转到.见鬼。

感谢任何人愿意改变我的想法!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-11-21 13:28:35

为了异步编程,你必须把你的思想倒转出来。我是凭经验说话的。:)

我只是用错了异步调用吗?我的理解错了吗?

不是的。异步代码很难编写(不要忘记错误处理),维护也非常困难。

这就是asyncawait被发明的原因。

如果您能够升级到VS2012,那么您可以使用Microsoft.Bcl.Async (目前处于测试版)编写如下代码:

代码语言:javascript
运行
复制
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);

写起来很容易。易于维护。

票数 2
EN

Stack Overflow用户

发布于 2012-11-21 11:21:18

异步就像你打了电话,得到了答录机,如果你想要回电话,就留下你的电话号码。第一种方法是调用数据,第二种方法是为返回调用留下的“数字”。

票数 1
EN

Stack Overflow用户

发布于 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上执行类似的操作。

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
void OnUserAction() {
  GetCurrencyCode().ContinueWith(GetCurrencyCodeCallback);
}

void GetCurrencyCodeCallback(Task<String> task) {
  if (!task.IsFaulted)
    Console.WriteLine(task.Result);
  else
    Console.WriteLine(task.Exception);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13492027

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档