我有这门课:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
我这样称呼:
private void SearchImageClicked(object sender, RoutedEventArgs e)
{
HttpContent content = api.getImages(SearchBox.Text, 0, 0, "png", 1);
// other code here
}
Run Code Online (Sandbox Code Playgroud)
但是当getImages返回时,我的程序会冻结.我放了一个断点, return task.Result;然后它去了.但是我也在getImages通话结束后设置了一个断点,它没有去那里,我的程序冻结了,我必须杀死进程才能让它停止.
怎么可能?
这是因为你混合同步和异步.此行导致死锁:
return task.Result;
Run Code Online (Sandbox Code Playgroud)
在doRequest,您正在使用await,它捕获当前的同步上下文(因为您没有指定ConfigureAwait(false).HttpClient.GetAsync(urlQuery)完成后,调度程序尝试在捕获的上下文上运行延续,即在UI线程上.但UI线程已经忙于等待为了doRequest完成,所以继续doRequest执行不能执行:你有一个死锁.
当你使用时async/await,你应该一直使用它; 你应该不同步等待异步方法来完成.在您的情况下,最简单的修复方法是getImages同步,并将使用代码更改为异步.
有关此问题的详细信息,请参阅Stephen Cleary 撰写的这篇文章.