WebClient DownloadStringAsync被阻止 - 从未完成

时间:2013-11-20 20:19:36

标签: c# mvvm windows-phone async-await deadlock

我的Windows Phone应用程序(使用MVVM)中的WebClient存在特定问题

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);
        }

同样,在await的行是等待数据的应用程序,但是DownloadStringTaskAsync永远不会完成,我的UI仍在加载。

任何想法可能出错?


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

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

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

2 个答案:

答案 0 :(得分:2)

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

使用async - await,您没有提供所有代码,但通过调用Wait()或{{1}可能会遇到几乎相同的问题在返回的Result上。如果用Task替换它,您的代码将起作用。虽然这需要您从await向上GetCoursesForDayFromApiAsJson()生成所有代码。

答案 1 :(得分:0)

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

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