2013-11-20 37 views
0

我有WebClient的具体问题,我的Windows Phone应用程序(使用MVVM)WebClient的DownloadStringAsync阻塞 - 没有完成

private string _lastCurrencyRatesJson; 
private bool _lastCurrencyRatesJsonLoaded = false; 

private void GetLastCoursesFromApiAsync() 
{ 

    var uri = new Uri(string.Format(OperationGetLastCourses, AppSettings.ApiEndpoint, AppSettings.ApiKey)); 
    var client = new WebClient { Encoding = Encoding.UTF8 }; 

    client.DownloadStringCompleted += client_DownloadStringCompleted; 
    client.DownloadStringAsync(uri); 
} 


void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 
     { 
      _lastCurrencyRatesJson = e.Result; 
      _lastCurrencyRatesJsonLoaded = true; 
     } 


public List<CurrencyRate> GetLastCourses() 
     { 
      var worker = new Thread(GetLastCoursesFromApiAsync); 
      worker.Start(); 

      while (!_lastCurrencyRatesJsonLoaded) 
      { 

      } 
..... 

的问题是,client_DownloadStringCompleted是从来没有发射,但是当我改变GetLastCourses这样:

public List<CurrencyRate> GetLastCourses() 
     { 
      var worker = new Thread(GetLastCoursesFromApiAsync); 
      worker.Start(); 

      // whetever here, but any while... 

client_DownloadStringCompleted被触发并获得数据。这意味着,连接是好的。

我有与DownloadStringTaskAsyn非常类似的问题。例如:

private async Task<string> GetCoursesForDayFromApiAsJson(DateTime date) 
     { 
      var uri = new Uri(string.Format(OperationGetCoursesForDay, AppSettings.ApiEndpoint, AppSettings.ApiKey, date.ToString(DateFormat))); 
      var client = new WebClient { Encoding = Encoding.UTF8 }; 

      return await client.DownloadStringTaskAsync(uri); 
     } 

同样,在与等待线应用等待数据,但DownloadStringTaskAsync是从来没有完成,我的UI仍在加载。

任何想法可能是错的?


状况一天前 因此,它看起来是WP应用程序是用一个线程的工作而已。这意味着,当前线程必须“完成”,然后是DownloadStringTaskAsync完成,并执行await下的代码。当我想要使用Task.Result时,我不能。决不。

当我创建另一个线程,并且正在尝试等待线程完成时(使用Join())时,创建的线程永远不会被启动,并且Join()之后的代码永远不会执行。

互联网上有任何例子,我绝对不知道,为什么存在一些DownloadStringTaskAsync时,它不适用。

+0

为什么你想用'Task.Result'工作?你应该使用'await'。 – svick

回答

2

您正在通过while循环阻止UI线程,同时,DownloadStringCompleted事件要在UI循环中执行。这会导致死锁,所以没有任何反应。你需要做的是让GetLastCourses()返回(以及任何方法调用),以便事件处理程序可以执行。这意味着处理结果的代码应该位于该事件处理程序中(不在GetLastCourses()中)。

随着async - await,你没有提供所有的代码,但它可能是因为您通过调用返回TaskWait()Result遇到几乎相同的问题。如果用await代替,你的代码就可以工作。尽管这需要你从GetCoursesForDayFromApiAsJson()开始使你的所有代码增加到async

+0

我是你说得对。我尝试了异步 - 等待版本,但现在,我在一些层面上遇到同样的问题:我的意思是我需要访问ViewModel构造函数中的item.Result。项目是任务

+1

@MiroslavHolec:所以现在你在其他地方造成同样的死锁;正确的解决方案是*仍然*使用'await'。我有一些关于[“异步”构造函数](http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html)和[“异步”属性](http: //blog.stephencleary。com/2013/01/async-oop-3-properties.html)。 –

0

我建议使用HttpClient class from Microsoft NuGet package,并使用异步/ AWAIT下载模式,而不是使用基于事件的WebClient类:

Uri uri = new Uri(string.Format(OperationGetLastCourses, AppSettings.ApiEndpoint, AppSettings.ApiKey)); 
using (HttpClient client = new HttpClient()) 
{ 
    string result = await client.GetStringAsync(uri); 
}