Don*_*zov 49 c# wpf multithreading asynchronous windows-phone-8
我创建了Windows Phone 8.1项目,我试图在按钮单击时运行异步方法GetResponse(字符串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;
}
Run Code Online (Sandbox Code Playgroud)
它会挂在task.Wait()上.
我将按钮单击方法更改为异步并在异步方法之前使用等待,我得到结果(await GetResponse<string>("url")
).有什么问题Task<List<string>> task = GetResponse<string>("url")
?我究竟做错了什么?
谢谢您的帮助!
Sri*_*vel 85
你是经典僵局的受害者.task.Wait()
或者task.Result
是UI线程中的阻塞调用,导致死锁.
不要阻止在UI线程中.永远不要这样做.等待它.
private async void Button_Click(object sender, RoutedEventArgs
{
var task = GetResponseAsync<MyObject>("my url");
var items = await task;
}
Run Code Online (Sandbox Code Playgroud)
顺便问一下,你为什么要把WebException
它扔掉呢?如果你根本不抓住它会更好.两者都是一样的.
此外,我可以看到你将异步代码与GetResponse
方法中的同步代码混合在一起.StreamReader.ReadToEnd
是一个阻止电话 - 你应该使用StreamReader.ReadToEndAsync
.
同样使用"Async"后缀来返回一个Task或异步以遵循TAP("基于任务的异步模式")约定,如Jon所说.
当您解决了上述所有问题时,您的方法应如下所示.
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);
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 26
这就是杀了你的原因:
task.Wait();
Run Code Online (Sandbox Code Playgroud)
这是阻止UI线程直到任务完成 - 但任务是一个异步方法,它会在"暂停"并等待异步结果后尝试返回UI线程.它无法做到这一点,因为你阻止了UI线程......
有没有在你的代码真的看起来像它需要在UI线程上的反正,但假设你真的不希望它在那里,你应该使用:
private async void Button_Click(object sender, RoutedEventArgs
{
Task<List<MyObject>> task = GetResponse<MyObject>("my url");
var items = await task;
// Presumably use items here
}
Run Code Online (Sandbox Code Playgroud)
要不就:
private async void Button_Click(object sender, RoutedEventArgs
{
var items = await GetResponse<MyObject>("my url");
// Presumably use items here
}
Run Code Online (Sandbox Code Playgroud)
现在,在任务完成之前,该方法将在调度继续触发后返回,而不是阻塞Button_Click
.(这就是async/await的工作方式,基本上.)
请注意,我也将重新命名GetResponse
,以GetResponseAsync
对清晰度.
归档时间: |
|
查看次数: |
75786 次 |
最近记录: |