0

我早些时候问过这个问题,但没有一个回应最终奏效。所以我有一个类,它发出一个 Web 请求以获取一串数据,以及该类中的一个方法,它调用该方法来执行此操作,然后返回字符串值。

我有 MainPage 类,一个 City 类(WebRequest 返回一个 JSON 字符串,这个类解析它并存储数据),我有一个 WebRetrieval 类。

在 MainPage 我有这个:

private void City_GoButton_Click(object sender, RoutedEventArgs e)
{
    City cityObject = new City();
    WebRetrieval wr = new WebRetrieval();

    string jsonString;
    string formattedString;

    if (String.IsNullOrWhiteSpace(CityID_Textbox.Text))
    {
        MessageDialog md = new MessageDialog("Please enter in a number");
        md.ShowAsync();
    }
    else 
    {
        long cityNum = Convert.ToInt64(CityID_Textbox.Text);
        string url = "http://honey.computing.dcu.ie/city/city.php?id=" + cityNum;

        jsonString =  wr.GetResult(url);
        formattedString = cityObject.ReturnFormattedString(jsonString);
    }
}

在网络检索类中,我有这个:

async public void GetInformation(string url)
{
    var client = new HttpClient();
    var response = await client.GetAsync(new Uri(url));
    result = await response.Content.ReadAsStringAsync();
}

public string GetResult(string url)
{
    GetInformation(url);
    return result;
}

奇怪的是,在 WebRetrieval 类中,在 GetInformation 方法内部,当它尝试进行响应时,程序会跳转到我的 City 类并失败,因为它接收到的字符串为空。它永远不会到达 GetInformation 方法内的结果行。

我有一种感觉,这与 GetInformation 是异步的并且响应中有 await 的事实有关,但我不知道如何解决它,因为另一个问题中的建议最终没有奏效。

希望有人可以帮助我。干杯

4

2 回答 2

2

你应该避免async void。我在我的 MSDN 文章Best Practices in Asynchronous Programming中解释了“为什么”的全部细节。

void是一种非常不自然的async方法返回类型。您应该只在编写async事件处理程序(必须返回void)时使用它。

因此,将所有async void方法转换为async Task(并遵循命名约定):

async public Task GetInformationAsync(string url)
{
  var client = new HttpClient();
  var response = await client.GetAsync(new Uri(url));
  result = await response.Content.ReadAsStringAsync();
}

必须await编辑这些任务:

public string GetResult(string url)
{
  await GetInformationAsync(url);
  return result;
}

但是编译器会抱怨如果你使用await,你必须让你的方法async,所以我们这样做:

public async Task<string> GetResultAsync(string url)
{
  await GetInformationAsync(url);
  return result;
}

await也是:

private void City_GoButton_Click(object sender, RoutedEventArgs e)
{
  ...
  jsonString = await wr.GetResultAsync(url);
  formattedString = cityObject.ReturnFormattedString(jsonString);
}

编译器再一次抱怨,所以我们通过调用方法来解决这个问题async(通常,我们会 make it async Task,但它必须是async void因为它是一个事件处理程序):

private async void City_GoButton_Click(object sender, RoutedEventArgs e)
{
  ...
  jsonString = await wr.GetResultAsync(url);
  formattedString = cityObject.ReturnFormattedString(jsonString);
}

你完成了。

你可能会发现我的async介绍很有帮助。

于 2013-11-12T18:32:26.540 回答
1

如果我理解正确的话,GetResult就是调用GetInformation,这是一种async方法。基本上,内部GetResult不需要等待GetInformation调用完成即可完成。你有时间问题。

对此的一些可能的解决方案可能是标记GetResultasync,并让它等待GetInformation,或者返回一个值,然后您可以通过调用任务GetInformation来强制完成该值。.Result

于 2013-11-12T18:11:33.370 回答