質問

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.

役に立ちましたか?

解決

You're seeing a deadlock issue that I describe in detail on my blog.

I want to have two methods that read via http; one sync and one async.

That's your problem right there. Downloading an HTTP resource is a naturally asynchronous operation, so it should only have an asynchronous API.

他のヒント

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().
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top