【问题标题】:How to make an async httpclient web *response* to be handled until later (after calculations)如何使异步 httpclient web *response* 待稍后处理(计算后)
【发布时间】:2018-07-07 10:53:52
【问题描述】:

我进行了 httpclient 调用,然后想立即开始计算。我不希望计算受到返回响应的干扰。计算最多可能需要 3 秒。

伪代码

{
    var data = await GetDataFromCloud();

    //do calculations - highly time sensitive!
    DoCalc() //A recursive job or nested loop *the response is occurring within this call :(

    //I want the response to occur here after the work above has completed :)

}

锁在这里工作。 此代码位于 UI 线程上的异步函数中。 DoCalc 是非阻塞的。 UI 线程没有被阻塞。

【问题讨论】:

    标签: c# multithreading async-await locking httpclient


    【解决方案1】:

    假设您不需要从GetDataFromCloud() 返回的数据来实际执行计算,您可以从方法中获取任务而不是等待它,进行计算然后等待它。

    类似这样的:

    {
        var dataTask = GetDataFromCloud(); // Starts the task and returns it
    
        //do calculations - highly time sensitive!
        DoCalc()
    
        var data = await dataTask; // Wait for the task to finish (if it hasn't already)
    }
    

    当然,如果计算需要数据,那么您需要先等待所有数据下载完毕,或者通过抓取HttpResponseMessage 并读取数据来处理“流”数据手动输入内容。

    编辑:

    还值得注意的是,如果请求中出现问题(即抛出异常),使用这种方法直到await 才会知道。

    【讨论】:

    • 我不需要响应结果,但我确实需要在计算之前立即发生请求。你的建议会这样做吗?
    • 请求将立即发送,但不会等待响应(直到await
    • 不错!我会试一试的。
    【解决方案2】:

    这正是我们想要使用 async-await 的场景!

    当您的线程必须空闲等待其他事情完成时,异步等待很有用。例如,要读取的文件、要执行的数据库查询、要下载的网页。通常情况下,其他人正在做工作,而您的线程只是在等待工作完成。

    您可以“做其他事情而不是无所事事地等待”的功能被声明为异步。读取文件时见Stream.ReadAsync,执行数据库查询时见Dapper.SQLMapper.QueryAsync,实体框架中的数据库查询见ToListAsyncFirstOrDefaultAsync,互联网下载等见WebClient.DownloadFileAsync

    如果您调用异步函数,则返回值为Task 而不是void,或者是Task<TResult> 而不是TResult。有一个例外:事件处理程序不会产生任务,而是无效。

    如果您想从 async-await 中受益,您必须定义您的函数 async 并返回 TaskTask<TResult>

    当您调用异步函数时,您可能会确定该函数中的某处是等待。事实上,如果您忘记在某个地方等待,您的编译器会警告您。同样,如果您定义函数 async 但忘记调用另一个异步函数,则会收到警告

    调用其他异步函数后,只要不需要调用结果,就可以继续工作。只要您需要结果,您就可以等待任务。

    如果您开始等待任务,但数据仍然不可用,那么您的线程将向上调用其调用堆栈,以查看您的调用者是否有事要做,直到您的调用者等待。再次向上调用堆栈,看看是否有工作要做等。

    async Task<MyResult> GetMyData(...)
    {
        Task<SomeData> taskGetData = GetDataFromCloud(...);
    
         // while the data is being fetched, we can continue working
         DoSomethingElse();
    
         // now we need the data:
         SomeData fetchedData = await taskGetData;
         MyResult result = ProcessFetchedData(fetchedData);
         return result;
    }
    

    帮助我理解 async-await 的是 this interview with Eric Lippert。在中间某处搜索 async-await。

    this article by the ever so helpful Stephen Cleary也帮助了我

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-08
      • 2018-04-12
      • 2019-11-14
      • 2014-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-01
      相关资源
      最近更新 更多