【问题标题】:What happens in long running async method before delay?在延迟之前长时间运行的异步方法会发生什么?
【发布时间】:2023-03-24 08:15:01
【问题描述】:

我有一个每秒向我的服务器发送请求的方法。

public async Task StartRequestProcess(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCanecllationRequested)
    {
       var result = await GetDataFromServerAsync();
       await Task.Delay(1000, stoppingToken);
    }
}

但我的 GetDataFromServerAsync() 方法有时需要 10 或 15 秒。

这段时间(10 或 15 秒)做什么?

进程会等到完成长请求吗?还是每秒都会发送新请求而无需等待?

【问题讨论】:

    标签: c# async-await task-parallel-library


    【解决方案1】:

    我有一个方法可以每秒向我的服务器发送一个请求。

    不,你没有。请不要用虚假陈述提出问题;这让他们很难回答!

    您的工作流程是:

    • 请求数据
    • 等待数据到达——这就是异步等待的意思。 await异步等待
    • 数据到达后,再次异步暂停一秒钟
    • 重复。

    这不是“每秒发送一个请求”的工作流程。这就是“在最后一个请求成功后一秒发送请求”的工作流程。

    这段时间(10 或 15 秒)做什么?

    异步等待。您说要异步等待数据可用,这就是它的作用。在异步等待期间,可以安排其他任务在线程上执行。

    工作流会等到长请求完成吗?

    是的。它将异步等待。同样,这就是await 的意思。这意味着异步等待

    新请求是否会每秒发送一次而无需等待?

    没有。您说要等到收到数据然后暂停一秒钟,所以会发生这种情况。

    【讨论】:

    • 您可能想详细说明“同步”和“异步”等待之间的区别,因为必须非常仔细地阅读答案才能注意到它们之间的区别。
    • @Joker_vD:我同意你的观点,但我并不打算将其作为异步工作原理的教程;如果读者不清楚异步等待和同步等待之间的区别是什么,那么他们需要自行阅读以了解该功能是什么。
    【解决方案2】:

    TAP(任务异步模式)的整个想法是,单个线程可以“同时”为许多事情提供服务,因为它可以在await 正在进行的任何时候回到它之前所做的事情。这就是为什么方法上的异步标记往往在层次结构中的每个方法上,从您编写的代码(例如您的控制器 Get 方法)的第一点到您调用的每个方法,一直到您需要的地方等待诸如 db 或网络 IO 之类的东西。

    遇到await 有点像抛出一个未捕获的异常- 控制流正确地备份整个方法堆栈,即您的代码,然后从顶部返回到之前发生的任何事情,在外部你的代码。抛出异常和等待状态机的区别在于,当正在等待的任务完成时,去执行其他事情的线程会回到等待的地方并从那里继续

    它之前所做的是高度上下文相关的 - 在您的情况下,它可能是“等待 TCP 客户端连接并发送一些数据”

    现在,在您的代码中,线程恢复到之前所做的工作 - 您说它需要 15 秒,因此线程将在 15 秒内忙于其他事情,然后它会回来等待您的 1000 毫秒任务完成,然后它将循环并发出另一个请求。实际上,这意味着您的代码每 16 秒就会发出一次请求;不是您希望的每一秒的请求。使用计时器

    【讨论】:

      【解决方案3】:

      当您调用 await GetDataFromServerAsync() 时,您的方法将在异步操作完成后恢复执行,例如 10 到 15 秒后。只有这样,您才会异步等待一秒钟。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-03
        • 2018-06-13
        • 1970-01-01
        相关资源
        最近更新 更多