0

I've an extension method for WebClient (WP8)

public static Task<string> DownloadStringTask(this WebClient webClient, Uri uri)
    {
    var tcs = new TaskCompletionSource<string>();

    webClient.DownloadStringCompleted += (s, e) =>
        {
            if (e.Error != null)
            {
                tcs.TrySetException(e.Error);
            }
            else if (e.Cancelled)
            {
                tcs.TrySetCanceled();
            }
            else
            {
                tcs.TrySetResult(e.Result);
            }
        };

    webClient.DownloadStringAsync(uri);

    return tcs.Task;
}

and the call to this method

public string GetResult()
{
    var task = new WebClient().DownloadStringTask(new Uri("http:\\www.foo.com"));

    return task.Result;
}

The DownloadStringCompleted is never executed and obviously there is no result, if I press the pause button on VS always is waiting in task.Result.

Any idea?

Thanks in advance.

Neil Turner
  • 2,712
  • 2
  • 18
  • 37
Tori
  • 57
  • 5

2 Answers2

1

Is GetResult executed from the main thread? In that case, it may be a deadlock. If I remember correctly, the callback of the WebClient is executed on the main thread, which cannot happen since you're blocking it by calling task.Result.

You have multiple ways to prevent this issue:

  • Use a HttpWebRequest instead of a WebClient

  • Call GetResult from another thread

  • Execute the task asynchronously by using task.ContinueWith instead of directly task.Result

  • Rewrite your method using async/await keywords

Kevin Gosse
  • 38,392
  • 3
  • 78
  • 94
  • HttpClient has the very same issue with deadlock, most probably because it uses WebClient behind the scenes. Synchronous web requests are really not possible on Windows Phone, even if you're using ConfigureAwait to schedule web request's completion on other thread than the main one. Long hours spent on trying to make this work with no avail. – Haspemulator May 23 '13 at 15:50
  • @Haspemulator I don't know for `HttpClient` as I haven't used it much yet, but `HttpWebRequest` should work – Kevin Gosse May 23 '13 at 16:03
  • Calling the method from another thread solved the problem, thanks! – Tori Jun 05 '13 at 08:16
0

task.Result blocks the executing thread until the result is available. For me it seems that your code just defeats the purpose of making the request asynchronous. As KooKiz mentioned, use some truly asynchronous API to get the result, such as task.ContinueWith or await task.

Haspemulator
  • 11,050
  • 9
  • 49
  • 76