2013-06-22 149 views
2

我的代码块:任务<T>冻结UI线程

Dispatcher.BeginInvoke(() => { 
      var Users = GetUsers().Result; 
      // proceed... 
     } 

private Task<List<User>> GetUsers() 
{ 
    var tcs = new TaskCompletionSource<List<User>>(); 
    wbclient.DownloadStringCompleted += (o, e) => { 
       if (e.Error == null) 
        tcs.SetResult(JsonConvert.DeserializeObject<List<User>>(e.Result)); 
       else 
        tcs.TrySetException(e.Error); 
       }; 
    wbclient.DownloadStringAsync(someUri); 
    return tcs.Task; 
} 

我想,然后再继续让所有的用户。所以我在调度员中调用GetUser方法。我只想等到DownloadStringCompleted事件发生,然后返回。但通过上面的代码,UI会冻结。任何帮助表示赞赏。

注:

我使用windows-phone 7,不支持asyncawait

+1

不,不。没有。 Dispatcher **强制**它在UI线程中运行。 –

+0

@newStackExchangeInstance仍然UI冻结! –

+0

@AshokDamani:是的,因为你正在使用'任务 .Result'。阅读该财产的文档。 –

回答

3

您应该使用一个延续和删除Dispatcher.BeginInvoke呼叫和.Result呼叫你的主线程是阻止:

GetUsers().ContinueWith(t => 
{ 
    List<User> users = t.Result; 
    this.TextBlock1.Text = "Complete"; 
}, TaskScheduler.FromCurrentSynchronizationContext()); 

注意如何我已经使用在TaskScheduler.FromCurrentSynchronizationContext()通话继续确保这个延续在主UI线程上编组。

+2

请注意,这假定这个代码已经在UI线程上执行。 (否则,当前同步上下文不会是正确的。) –

+0

'GetUsers()ContinueWith(T => 。{ 列表用户= t.Result; MessageBox.Show( “完成”);} , TaskScheduler.FromCurrentSynchronizationContext());' 好的UI不会冻结。 但messageBox不显示呢? –

+0

代码执行是否进入延续?当你在其中放置断点时会发生什么?请求是否成功?你能够获得用户吗? –

1

您可以在Windows Phone 7上使用异步等待,您只需将this nuget packet安装到解决方案中的所有项目中即可。即使某些项目与Windows Phone 8共享,或者某些项目是可移植的类库,也可以很好地工作。很有帮助。

所以,你应该那么可以使用:var Users = await GetUsers();

顺便说一句,你总是可以使用HttpClient的,而不是Web客户端的:http://nuget.org/packages/Microsoft.Net.Http/2.1.10