2014-03-30 54 views
0

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

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()是造成僵局,所以我创建了以下测试类:

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,还推出了如在同一个解决方案中单独的项目。我们到达'结果='行,但该行永远不会返回。我知道IIS正在运行,并且网络链接正在工作,因为我可以使用手机中的IE访问URI。

+0

你是否试图阻止UI线程?这是一个非常糟糕的主意。它没有帮助,你已经显示的代码,甚至不会编译... –

+0

嗨,乔恩,我很抱歉 - 我写这个问题的方式不清楚。我已编辑希望解决。我可以发布剩余的代码,但这只是WebClient的设置,所以似乎没有任何意义。但如果有帮助,会做。 – jbhelicon

回答

1

你看到一个deadlock issue that I describe in detail on my blog

我想通过http读取两种方法;一个同步和一个异步。

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

+0

博客文章是dispositive;谢谢。 “一路下跌”的建议是一个新口头禅。 – jbhelicon

1

是的,你目前正在创建一个死锁。

您使用异步/等待,这意味着,当任务被完成DownloadStringTaskAsync返回,继续将计划继续从那里离开,并回到UI线程loadAsync

但是,由于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(). 
} 
+0

这是我试过的东西之一,但它仍然挂起,所以可能会有更有趣的事情发生。我已经修改了这个问题以包含新的精简代码以及发生了什么。 – jbhelicon

+0

@jbhelicon:可能是'DownloadStringTaskAsync'本身在UI线程上调度了一些操作。基本上,当你开始做一些你不应该(在这种情况下阻塞UI线程)的东西时,任何假设你“行为正常”的东西都可能开始失败。 –

+0

够公平的,尽管你会认为这将是一件奇怪的事情。但是我发现WebClient会在UI线程上引发DownloadFileCompleted事件,所以可能就是这样!有没有简单的方法来测试这个猜想?即使用新线程启动并调用Test,并在完成时恢复调用线程? – jbhelicon