如何等待web客户端OpenReadAsync完成

本文关键字:web 客户端 OpenReadAsync 完成 等待 何等待 | 更新日期: 2023-09-27 18:15:50

我在Windows Phone 8.1应用程序中使用WebClient从互联网下载一些东西。下面是我在我的应用程序中使用的示例代码-我调用下面的方法,但我的web客户端没有等待完成读取操作并在OpenReadAsync调用后立即返回。

我怎么能确保我的方法返回操作必须等到OpenReadCompleted事件完成?我见过许多类似的问题,但都找不到解决办法。

MyCustomObject externalObj;  // my custom object
private static void CheckNetworkFile()
{
    try
    {
        WebClient webClient = new WebClient();
        webClient.OpenReadCompleted += (s, e) =>
        {
          externalObj = myReadWebclientResponse(e.Result); // my custom method to read the response
        };
        webClient.OpenReadAsync(new Uri("http://externalURl.com/sample.xml", UriKind.Absolute));                
    }
    catch (Exception)
    {
      externalObj = null;
    }
}

如何等待web客户端OpenReadAsync完成

我建议您将WebClient.OpenReadTaskAsync与。net 4.5中引入的async/await关键字组合使用。您需要将async关键字添加到您的方法中,使其返回Task,并且建议以Async后缀结束您的方法:

MyCustomObject externalObj;
private static async Task CheckNetworkFileAsync()
{
    try
    {
        WebClient webClient = new WebClient();
        Stream stream = await webClient.OpenReadTaskAsync(new Uri("http://externalURl.com/sample.xml", UriKind.Absolute));                
        externalObj = myReadWebclientResponse(stream);
    }
    catch (Exception)
    {
      externalObj = null;
    }
}
编辑:

正如你所说,WebClient.OpenReadTaskAsync不能用于WP8.1,所以让我们创建一个扩展方法,所以它将是:

public static class WebClientExtensions 
{
    public static Task<Stream> OpenReadTaskAsync(this WebClient client, Uri uri)
    {
       var tcs = new TaskCompletionSource<Stream>();
       OpenReadCompletedEventHandler openReadEventHandler = null;
       openReadEventHandler = (sender, args) => 
       {
          try 
          {
             tcs.SetResult(args.Result);
          } 
          catch (Exception e)
          {
             tcs.SetException(e);
          }
       };
       client.OpenReadCompleted += openReadEventHandler;
       client.OpenReadAsync(uri);
       return tcs.Task;
    }
}

现在你可以在你的WebClient上使用它了。

您可以在async-await wiki中找到很棒的阅读材料,并且只需在搜索栏中过滤该标签。

我希望这不是太偏离主题,但是其他正在研究这个问题的人可能想知道上面的代码示例也可以用于Silverlight中的WCF调用。一定要先添加Microsoft.Bcl.Async NuGet包。下面是一个WCF代码示例:

  public static async Task<string> AuthenticateAsync(string userName, string password)
    {
        var dataAccessServiceClient = new DataAccessServiceClient("DataAccessService");
        var taskCompletionSource = new TaskCompletionSource<string>();
        EventHandler<AuthenticateCompletedEventArgs> completedHandler = null;
        completedHandler = (s, args) =>
        {
            try
            {
                taskCompletionSource.SetResult(args.Result);
            }
            catch (Exception e)
            {
                taskCompletionSource.SetException(e);
            }
        };
        dataAccessServiceClient.AuthenticateCompleted += completedHandler;
        dataAccessServiceClient.AuthenticateAsync(userName, password);
        return await taskCompletionSource.Task;
    }

可以这样调用:

var result = await AuthenticateAsync(username, password);