how to wait for webclient OpenReadAsync to complete

蹲街弑〆低调 提交于 2019-12-07 16:27:31

问题


I am using WebClient to download some stuff from internet in Windows Phone 8.1 app. Below is the sample code i am using in my app - where i am calling below method, but my webclient is not waiting to complete the read operation and returning immediately after OpenReadAsync call.

how can i make sure that my method return operation must wait till OpenReadCompleted event is completed? I have seen multiple similar questions, but couldn't find a solution.

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;
    }
}

回答1:


I would advise you to use WebClient.OpenReadTaskAsync with a combination of the async/await keywords introduced in .NET 4.5 instead. You need to add the async keyword to your method, make it return a Task and it is advisable to end your method with the Async postfix:

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;
    }
}

Edit:

As you said, WebClient.OpenReadTaskAsync isn't available for WP8.1, So lets create an Extension Method so it will be:

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;
    }
}

Now you can use it on your WebClient.

You can find great reading material in the async-await wiki and by simply filtering by that tag in the search bar.




回答2:


I hope this is not too off topic, but others who are researching this might like to know that the above code sample can also be used for WCF calls in Silverlight. Be sure to add the Microsoft.Bcl.Async NuGet package first. Here is a WCF code example:

  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;
    }

It can be called like this:

var result = await AuthenticateAsync(username, password);


来源:https://stackoverflow.com/questions/25051674/how-to-wait-for-webclient-openreadasync-to-complete

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!