how to wait for webclient OpenReadAsync to complete

12,185

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.

Share:
12,185
Mahender
Author by

Mahender

Updated on June 05, 2022

Comments

  • Mahender
    Mahender almost 2 years

    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;
        }
    }
    
  • Mahender
    Mahender over 9 years
    Thanks for the reply, actually this OpenReadTaskAsync() is not in the WindowsPhone platform.
  • Sayed Abolfazl Fatemi
    Sayed Abolfazl Fatemi almost 9 years
    Salam, I think you must change "taskComplete" to "tcs.SetResult(...)"
  • Yuval Itzchakov
    Yuval Itzchakov almost 9 years
    @SayedAbolfazlFatemi Thanks for letting me know. Edited my answer.
  • Phil Cooper
    Phil Cooper about 8 years
    Thanks for the extension hint.
  • Christian Findlay
    Christian Findlay over 7 years
    OH MY GOD!!! This is the single most important code example for Silverlight I have ever seen. This not only works for REST calls, it also works for WCF calls. Up until now, I have been using the old async model without the async/await operators to call WCF/REST methods. Our code is littered with horrible event handlers everywhere and the code is like a maze to navigate. This will clean up our code immensely. I should mention though, that in order to use this, we must add the Microsoft.Bcl.Async NuGet package. That was the other key to unlocking this problem.