HttpClientt.SendAsync不等待/锁定执行

时间:2017-08-21 14:59:59

标签: c# async-await dotnet-httpclient

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

应该等待这个想法,但无论它做什么,执行都存在方法并返回到UI。当响应到达时执行恢复,但到那时UI已经更新了执行完成,而实际上它还没有完成。 等待所有调用方法。

设计(Task.Run(() => StartDownload(selectedSchedules));不等待初始方法,它启动UI方法执行触发httpclient的服务,当调用完成后UI应该随进度更新,但第二个httpClient.SendAsync被执行,执行返回到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);
        }
    }
}

调用链添加,从方法中删除不相关的代码

1 个答案:

答案 0 :(得分:4)

你的问题可能在于你的第一次打电话。

在您的代码中,您有:

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

这样做:它会调用StartDownload并立即继续执行。所有其他的东西(下载等)然后在后台发生。请记住,方法StartDownload不会阻止;它只返回一个Task对象。如果您没有awaitTask个对象,则代码将继续执行。

我猜你想要的是:致电StartDownload,等待它完成,然后更新进度。

快速解决方案是使用async标记按钮的事件处理程序,然后一直使用async。该方法看起来有点像这样:

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

我可以向Stephen Cleary推荐这篇博文,介绍async-await:https://blog.stephencleary.com/2012/02/async-and-await.html