This is one of these things where I thought that I knew exactly what is happening, but have been unable to figure how to fix it on Windows Phone 8. I want to have two methods that read via http; one sync and one async. The sync function is currently being called from the UI thread, but ultimately will probably not be. The relevant code looks like this:
private static string result;
public static string load() {
Task task = loadAsync();
task.Wait;
return result;
}
public async static Task < string > loadAsync() {
...
result = await webClient.DownloadStringTaskAsync(uri);
}
I intended that when I call Task.Wait() the UI thread will wait until the read completes; that's ok - I want the UI to pause until the read completes. But as written I appear to be creating a deadlock, so that everything hangs and the Download never completes, and presumably never starts. It makes sense that the task.wait() is causing the deadlock, so I created the following Test class:
public static class Test
{
const string apiUrl = @"http://169.254.21.12:51428/api/Q";
private static WebClient webClient;
private static Uri uri;
private static string result;
public static string Load()
{
webClient = new WebClient();
webClient.Headers["Accept"] = "application/json";
uri = new Uri(apiUrl);
try
{
Task<string> task = webClient.DownloadStringTaskAsync(uri);
result = task.Result;
}
catch (Exception e) { result = null; }
return result;
}
This class is running in the WP8 Emulator from VS13, talking to a local IIS, also launched as a separate Project in the same Solution. We get to the 'result =' line, but that line never returns. I know that IIS is running and the network link is working, since I can use IE in the phone to reach the URI.
Yes, you're currently creating a deadlock.
You're using async/await, which means that when the task returned by DownloadStringTaskAsync
completes, a continuation will be scheduled to continue loadAsync
from where it left off, and back in the UI thread.
However, that continuation is never going to actually run because the UI thread is busy waiting for a task to complete... and that task is only going to complete after continuation has run. Deadlock.
Just to block the UI thread, you don't need to use async
/await
at all:
// Method name changed to follow .NET conventions.
public static string Load() {
WebClient webClient = ...;
Task<string> task = webClient.DownloadStringTaskAsync(uri);
return task.Result; // Result blocks, just like Wait().
}
See more on this question at Stackoverflow