Aistis Taraskevicius
Aistis Taraskevicius

Reputation: 811

HttpClientt.SendAsync doesnt wait/lock execution

var httpResponseMessage = await httpClient.SendAsync(message).ConfigureAwait(false);
var dataStream = await httpResponseMessage.Content.ReadAsStreamAsync();

This by idea should be awaited, but no matter what it do executions exists the method and returns to UI. Execution resumes when responses arrives, but by that time UI has already updated that execution finished, when in fact it hasn't. All calling methods are awaited.

Initial method is not awaited by design (Task.Run(() => StartDownload(selectedSchedules)); which starts UI method executing services that triggers httpclient, when that call finished UI should update with progress, but the second httpClient.SendAsyncis executed, execution returns to UI

Task.Run(() => StartDownload(selectedSchedules)); //First call, initiated by a button

public async Task StartDownload(SchedulesList list)
{
    //var t = new Task(() => _scheduleServices.Download(list));
    //t.Start();
    //await t;
    await _scheduleServices.DownloadIwcfDb(list, UsbInfoModels);
}

public async Task Download(SchedulesList schedulesList)
{                         
    await DownloadDb(schedulesList);        
}

private async Task DownloadDb(SchedulesList schedulesList)
{
    using (var httpClient = new HttpClient())
    {
        var message = new HttpRequestMessage(new HttpMethod("POST"), ApiCallUrls.GetIwcfSchedules)
        {
            Content = new StringContent(JsonConvert.SerializeObject(schedulesList), Encoding.UTF8, "application/json")
        };

        httpClient.Timeout = TimeSpan.FromMinutes(20);
        var httpResponseMessage= await httpClient.SendAsync(message).ConfigureAwait(false);
        var dataStream = await httpResponseMessage.Content.ReadAsStreamAsync();
        using (Stream contentStream = dataStream, stream = new FileStream(Path.Combine(Directories.SomEDir, Directories.SomeFileName), FileMode.Create, FileAccess.Write, FileShare.None))
        {
            await contentStream.CopyToAsync(stream);
        }
    }
}

Call Chain Added, irrelevant code removed from the methods

Upvotes: 2

Views: 1628

Answers (1)

Florian Moser
Florian Moser

Reputation: 2663

You're problem probably lies within your first call.

In your code you have:

Task.Run(()=>StartDownload(selectedSchedules)); //First call, initiated by a button
//I assume afterwards you update the ProgressBar or give some other progress feedback

What this does is: It calls StartDownload and immediately continues execution. All the other stuff (downloading etc) is then happening in the background. Remember that the method StartDownload does not block; it simply returns a Task object. If you do not await that Task object, the code will simply proceed.

I guess what you wanted is: Call StartDownload, wait for it to finish, then update the progress.

A quick solution would be to mark your event handler of the button with async, and then use async all the way. The method would look a bit like this:

private async void HandleEvent()
{
    await StartDownload();
    //update progress
}

I can recommend you this blog post from Stephen Cleary for an introduction to async-await: https://blog.stephencleary.com/2012/02/async-and-await.html

Upvotes: 4

Related Questions