为什么我的程序在返回后会冻结?

时间:2017-03-05 15:54:11

标签: .net uwp

我有这堂课:

-o

我称之为:

public class ImgurAPI
{
    private string ClientId = "id";
    private string ClientSecret = "secret";
    private string BasicUri = "https://api.imgur.com/3/";
    private HttpClient HttpClient = new HttpClient();
    public ImgurAPI()
    {
        HttpClient.DefaultRequestHeaders.Add("Authorization", "Client-ID " + ClientId);
    }

    private async Task<HttpContent> doRequest(string urlQuery)
    {
        HttpResponseMessage response = await HttpClient.GetAsync(urlQuery);
        return response.Content;
    }
    public HttpContent getImages(string search, int minSizeX, int minSizeY, string imageType, int page)
    {
        var url = BasicUri + "gallery/search/top/" + page.ToString() + "/";
        url += "?q=" + search;
        Task<HttpContent> task = doRequest(url);
        return task.Result;
    }
}

但是当private void SearchImageClicked(object sender, RoutedEventArgs e) { HttpContent content = api.getImages(SearchBox.Text, 0, 0, "png", 1); // other code here } 返回时,我的程序会冻结。我在getImages上放了一个断点,它就在那里。但是我在return task.Result;调用之后还放了一个断点,它没有去那里,我的程序冻结了,我必须终止进程才能让它停止。

怎么可能?

3 个答案:

答案 0 :(得分:5)

这是因为您正在混合同步和异步。这一行导致死锁:

return task.Result;

doRequest中,您正在使用await,它会捕获当前的同步上下文(因为您没有指定ConfigureAwait(false)。当HttpClient.GetAsync(urlQuery)完成时,调度程序尝试在捕获的上下文上运行continuation,即在UI线程上运行。但是UI线程已经忙于等待doRequest完成,因此doRequest中的延续不能执行:你有僵局。

当你使用async/await时,你应该一直使用它;你应该同步等待异步方法完成。在您的情况下,最简单的解决方法是使getImages异步,并将使用代码更改为异步。

有关此问题的详细信息,请参阅Stephen Cleary的this article

答案 1 :(得分:1)

当你调用task.Result时,你基本上强迫你的调用线程等到另一个线程完成。

请参阅Task.Result

答案 2 :(得分:1)

您的<ta-emp ng-model="empCode" ng-change="OnChange()"></ta-emp> getImages也必须是SearchImageClicked

async

public async Task<HttpContent> getImages(string search, int minSizeX, int minSizeY, string imageType, int page)
{
    var url = BasicUri + "gallery/search/top/" + page.ToString() + "/";
    url += "?q=" + search;
    return await doRequest(url);
}