HttpClient GetAsync挂起

6

我有两个WP8应用程序中都有一个相同的方法。在相同的url和设备下,该方法在一个应用程序中有效,但在另一个应用程序中无效。在失败的应用程序中,GetAsync在调用后挂起。没有超时,没有异常。

以下是相关的方法:

    private async Task<Byte[]> DownloadData(string uri)
    {
        byte[] myDataBuffer = null;
        var newUri = new Uri(uri, UriKind.Absolute);
        var myWebClient = new HttpClient();

        var response = await myWebClient.GetAsync(newUri);
        if (response.Content.Headers.ContentType.MediaType == "text/plain"
            || response.Content.Headers.ContentLength < 200)
        {
            throw new Exception(await response.Content.ReadAsStringAsync());
        }
        myDataBuffer = await response.Content.ReadAsByteArrayAsync();
        return myDataBuffer;
    }

每次在一个特定的应用程序上都会发生这种情况,但另一个应用程序没有。设备相同。有人经历过这种行为吗?URL是有效的,代码是相同的。是否有可能影响这一点的项目设置?我在故障应用程序的另一部分使用了HttpClient, 在那里它可以正常工作。
我可以更改代码以使用HttpWebRequest,这样就可以正常工作。只是HttpClient不行。
我刚才发现,如果将该方法复制到我的button_click处理程序中,它也可以正常工作。在单独的类中使用此方法是否存在问题?对我来说这似乎很奇怪。
更新:
看起来导致出现问题的是多个层的异步方法调用它。在这个类中,我有
    public override byte[] GetImageData(string imageUri)
    {
        return GetImageDataAsync(imageUri).Result;
    }

    public async Task<byte[]> GetImageDataAsync(string imageUri)
    {
        return await DownloadData(imageUri);
    }

从我的button_click处理程序中,我调用GetImageData(uri)。如果我将其更改为await GetImageDataAsync(uri),它就能工作了。 Result不是在GetImageData中引用的正确属性吗?
这是一个测试网址:“http://www.rei.com/pix/common/REI_logo.gif”。

1
.Result 阻塞直到任务返回值。这不是 'async' 的问题,而是你的代码有意阻塞。无论如何,大多数 MVVM 框架都可以处理异步方法,因此您不应该需要调用 .Result。您使用的是哪个框架? - Panagiotis Kanavos
1个回答

14

调用ResultWait可能会导致死锁,正如我在博客中所解释的那样。

正确的解决方法是使用await。我假设您有某些原因希望同步阻塞,但最好使用await并找到一种在代码中使其正常工作的方法。


对的,正如你所看到的,我在GetImageDataAsync上使用了await。我使用的接口定义了非异步的GetImageData,所以我想聪明地从那里调用我的异步版本,但这就是它失败的地方。 - earthling
3
如果你确实需要同步版本,那么类似 return Task.Run(() => GetImageDataAsync(imageUri)).Result; 这样的代码应该会起作用。但这将抵消使用异步方法的所有优势,所以这不是一个好主意(特别是在 GUI 应用程序中,这可能会使界面冻结一段时间)。 - svick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接