我创建了 Windows Phone 8.1 项目并尝试运行 async
方法 GetResponse<T>(string url)
单击按钮并等待方法完成,但方法永远不会完成。这是我的代码:
private void Button_Click(object sender, RoutedEventArgs
{
Task<List<MyObject>> task = GetResponse<MyObject>("my url");
task.Wait();
var items = task.Result; //break point here
}
public static async Task<List<T>> GetResponse<T>(string url)
{
List<T> items = null;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
var response = (HttpWebResponse)await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
try
{
Stream stream = response.GetResponseStream();
StreamReader strReader = new StreamReader(stream);
string text = strReader.ReadToEnd();
items = JsonConvert.DeserializeObject<List<T>>(text);
}
catch (WebException)
{
throw;
}
return items;
}
它将卡在 task.Wait()
上.
我将按钮点击方法更改为 async
并使用 await
在 async
之前方法,我得到结果(await GetResponse<string>("url")
)。 Task<List<string>> task = GetResponse<string>("url")
有什么问题?
我做错了什么?
感谢您的帮助!
最佳答案
您是经典僵局的受害者。 task.Wait()
或 task.Result
是导致死锁的 UI 线程中的阻塞调用。
Don't block in the UI thread .永远不要这样做。只需等待
即可。
private async void Button_Click(object sender, RoutedEventArgs
{
var task = GetResponseAsync<MyObject>("my url");
var items = await task;
}
顺便说一句,为什么要捕获 WebException
并将其扔回去?如果你根本不捕获它会更好。两者相同。
我还看到您在 GetResponse
方法中将异步代码与同步代码混合在一起。 StreamReader.ReadToEnd
是一个阻塞调用——您应该使用 StreamReader.ReadToEndAsync
。
还对返回任务或异步的方法使用“Async”后缀,以遵循 TAP(“基于任务的异步模式”)约定,如 Jon says .
当您解决了上述所有问题后,您的方法应该如下所示。
public static async Task<List<T>> GetResponseAsync<T>(string url)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
var response = (HttpWebResponse)await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
Stream stream = response.GetResponseStream();
StreamReader strReader = new StreamReader(stream);
string text = await strReader.ReadToEndAsync();
return JsonConvert.DeserializeObject<List<T>>(text);
}
关于c# - 单击按钮调用异步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28601678/