【问题标题】:HttpClientt.SendAsync doesnt wait/lock executionHttpClient.SendAsync 不等待/锁定执行
【发布时间】:2017-08-21 14:59:58
【问题描述】:
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);
        }
    }
}

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

【问题讨论】:

  • 这个运行的方法是否设置为异步
  • 请提供调用函数的源代码(使用Task.Run()的那个)
  • @BenSteele 是的,必须使用 httpclient ,添加调用链
  • @FlorianMoser 添加了完整的调用链,发出了不必要的代码,因此有些方法看起来很轻量级

标签: c# async-await dotnet-httpclient


【解决方案1】:

您的问题可能出在您的第一次通话中。

在您的代码中:

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 对象。如果你不 await 那个 Task 对象,代码将简单地继续。

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

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

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

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

【讨论】:

  • 实际上证明我的代码有效,我 99% 确信它之前已经退出,一定没有正确完成我的最新更改,但我会接受你的回答,因为它可能对大多数人都有帮助案例。虽然我相当确定我不需要异步事件处理程序来等待我的执行,因为从内部等待执行并沿链更新 UI(该部分被省略,因为与实际执行无关)
猜你喜欢
  • 2013-10-28
  • 1970-01-01
  • 2013-11-11
  • 1970-01-01
  • 2012-04-27
  • 2017-02-15
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
相关资源
最近更新 更多