在UI线程上同步使用DownloadStringTaskAsync

时间:2014-03-30 16:46:42

标签: multithreading windows-phone-8 webclient

这是我认为我确切知道发生了什么的事情之一,但是我无法想象如何在Windows Phone 8上修复它。我希望有两种方法可以通过http读取;一个同步和一个异步。目前正在从UI线程调用同步函数,但最终可能不会。 相关代码如下所示:

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

我打算在调用Task.Wait()时,UI线程将等待读取完成;没关系 - 我希望UI暂停,直到读完成。但正如所写,我似乎正在创建一个死锁,所以一切都挂起,下载永远不会完成,大概永远不会开始。 task.wait()导致死锁是有道理的,所以我创建了以下Test类:

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

这个类在VS13的WP8模拟器中运行,与本地IIS通信,也在同一个解决方案中作为单独的项目启动。我们到达'result ='行,但该行永远不会返回。我知道IIS正在运行且网络链接正常,因为我可以在手机中使用IE来访问URI。

2 个答案:

答案 0 :(得分:1)

是的,您目前正在制造僵局。

您正在使用async / await,这意味着当DownloadStringTaskAsync返回的任务完成时,将继续安排继续loadAsync从它停止的位置继续,并返回UI线程

但是,该延续永远不会实际运行,因为UI线程忙于等待任务完成......并且该任务仅在继续运行后才能完成。死锁。

只是为了阻止UI线程,您根本不需要使用async / await

// 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().
}

答案 1 :(得分:1)

您看到deadlock issue that I describe in detail on my blog

  

我希望有两种方法可以通过http读取;一个同步和一个异步。

那就是你的问题。下载HTTP资源是一种自然异步操作,因此它应该只有一个异步API。