Miroslav Holec
Miroslav Holec

Reputation: 3217

WebClient DownloadStringAsync blocked - never finished

I have specific problem with WebClient in my Windows Phone app (using MVVM)

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)
            {

            }
.....

The problem is that client_DownloadStringCompleted is never fired BUT when I change GetLastCourses this way:

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

            // whetever here, but any while...

client_DownloadStringCompleted is fired and data are obtained. It means, connectivity is ok.

I had very similar problems with DownloadStringTaskAsyn. Example:

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

Again, at the line with await is application waiting for the data but the DownloadStringTaskAsync is never finished and my UI is still loading.

Any ideas what could be wrong?


SITUATION ONE DAY AGO So, it looks that WP application is working just with one thread. It means, current thread have to be "finished" and then is DownloadStringTaskAsync finished and the code under the await executed. When I want to work with Task.Result I can not. Never.

When I create another Thread and I am trying to wait for thread completetion (using Join()), created Thread is never finsihed and the code after Join() is never executed.

There is any example on the Internet and I absolutely don't know, why exists some DownloadStringTaskAsync when it is not applicable.

Upvotes: 0

Views: 1279

Answers (2)

Martin Suchan
Martin Suchan

Reputation: 10620

I'd recommend to use the HttpClient class from Microsoft NuGet package and use the async/await downloading pattern rather than using event-based WebClient class:

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

Upvotes: 0

svick
svick

Reputation: 244757

You're blocking the UI thread by your while loop and at the same time, the DownloadStringCompleted event wants to execute on the UI loop. This causes a deadlock, so nothing happens. What you need to do is to let GetLastCourses() return (and whatever method calls that), so that the event handler can execute. This means that the code that handles the results should be in that event handler (not in GetLastCourses()).

With async-await, you didn't provide all of your code, but it's likely that you're encountering pretty much the same issue by calling Wait() or Result on the returned Task. If replace that with await, you code will work. Though that requires you to make all your code from GetCoursesForDayFromApiAsJson() up async.

Upvotes: 2

Related Questions