C# 如何等待webclient OpenReadAsync完成

C# 如何等待webclient OpenReadAsync完成,c#,windows-phone-8.1,async-await,task-parallel-library,webclient,C#,Windows Phone 8.1,Async Await,Task Parallel Library,Webclient,我正在使用WebClient在Windows Phone 8.1应用程序中从internet下载一些东西。 下面是我在我的应用程序中使用的示例代码——我调用了下面的方法,但我的webclient并没有等待完成读取操作并在OpenReadAsync调用后立即返回 如何确保方法返回操作必须等到OpenReadCompleted事件完成? 我见过多个类似的问题,但找不到解决方案 MyCustomObject externalObj; // my custom object private stat

我正在使用WebClient在Windows Phone 8.1应用程序中从internet下载一些东西。 下面是我在我的应用程序中使用的示例代码——我调用了下面的方法,但我的webclient并没有等待完成读取操作并在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;
    }
}
我建议您使用.NET4.5中引入的关键字组合。您需要将
async
关键字添加到方法中,使其返回
任务
,建议使用
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;
    }
}
公共静态类WebClientTextensions
{
公共静态任务OpenReadTaskAsync(此WebClient客户端,Uri)
{
var tcs=new TaskCompletionSource();
OpenReadCompletedEventHandler openReadEventHandler=null;
openReadEventHandler=(发送方,参数)=>
{
尝试
{
tcs.SetResult(args.Result);
} 
捕获(例外e)
{
tcs.SetException(e);
}
};
client.OpenReadCompleted+=openReadEventHandler;
OpenReadAsync(uri);
返回tcs.Task;
}
}
现在您可以在
网络客户端上使用它了


您可以在中找到很好的阅读材料,只需在搜索栏中按该标记进行筛选。

我希望这不是太离题,但其他正在研究这一点的人可能想知道,上面的代码示例也可以用于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;
    }

使方法
异步
。如果您不知道这意味着什么,请阅读C#中的
async
方法。感谢@Alxandr的回复,我确实尝试过使用async/wait,但行为相同。OpenReadCompleted事件在方法返回调用后完成。感谢您的回复,实际上此OpenReadTaskAsync()不在WindowsPhone平台中。Salam,我认为您必须将“taskComplete”更改为“tcs.SetResult(…)”@SayedBolfazlfatemi感谢您让我知道。编辑了我的答案。谢谢你的扩展提示。哦,我的上帝!!!这是我见过的Silverlight最重要的代码示例。这不仅适用于REST调用,也适用于WCF调用。到目前为止,我一直在使用没有async/await操作符的旧异步模型来调用WCF/REST方法。我们的代码到处都是可怕的事件处理程序,代码就像一个迷宫。这将极大地清理我们的代码。但是我应该提到,为了使用它,我们必须添加Microsoft.Bcl.Async NuGet包。这是解开这个问题的另一把钥匙。
var result = await AuthenticateAsync(username, password);