我有一种每秒发送请求到我的服务器的方法。
public async Task StartRequestProcess(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCanecllationRequested)
{
var result = await GetDataFromServerAsync();
await Task.Delay(1000, stoppingToken);
}
}
但是我的GetDataFromServerAsync()
方法有时需要10或15秒。
这段时间(10或15秒)是什么?
流程会等到完整的长请求吗?还是新的请求会每秒发送而无需等待?
我有一种每秒发送请求到我的服务器的方法。
不,你不知道。请不要以虚假陈述来提出问题;这使他们很难回答!
您的工作流程是:
await
是异步等待。不是工作流“每秒发送一个请求”。那就是工作流“在上一个请求成功之后一秒钟发送一个请求”。
这段时间(10或15秒)是什么?
异步等待。您说要异步等待,直到数据可用为止,这就是它的作用。在异步等待期间,可以安排其他任务在线程上执行。
工作流会等到长请求完成后吗?
是。它将等待异步。同样,这就是await
的意思。这表示异步等待。
新请求是否会在不等待的情况下每秒发送一次?
没有您说要等到收到数据后再暂停一秒钟,这就是发生的情况。
TAP(任务异步模式)的整个思想是,单个线程可以“同时”服务许多事情,因为只要await
正在进行,它就可以返回到之前的工作。这就是为什么在方法上的异步标记倾向于在层次结构中从您编写的代码的第一点(例如,您的控制器的Get方法)到您调用的每个方法的正确位置,一直指向正确的位置等待诸如数据库或网络IO之类的东西。
遇到await
有点像抛出未捕获的异常控制流,它会正确地备份您的代码的整个方法堆栈,然后从头开始,返回到您外部的所有内容码。引发的异常和等待状态机之间的区别在于,当等待任务完成时,去做其他事情的线程将返回到等待位置,并从那里继续进行]
之前的操作是高度上下文的-在您的情况下,可能是“等待TCP客户端连接并发送一些数据”
现在,在您的代码中,线程返回到之前的操作-您说这需要15秒,因此线程将自己忙于其他事情15秒,然后它将返回并等待您的1000ms任务执行完成,然后它将循环并发出另一个请求。实际上,这意味着您的代码每16秒就会发出一个请求;而不是您希望的每秒请求。使用计时器
[当您调用await GetDataFromServerAsync()
时,异步操作完成后,例如10到15秒后,将恢复执行方法。只有这样,您才能异步等待另外一秒钟。
您的代码中有一个明显的问题,看不到吗?
[通常,async方法的目的是在进行异步操作时释放前台线程。
这对您意味着什么,当程序到达代码GetDataFromServerAsync()
时,它将立即释放当前while
循环周期的主前台线程,然后再次启动它。
一旦GetDataFromServerAsync()
请求线程中的数据被阻塞一秒钟。并且在将取消令牌设置为true
while
之前,周期可能已经尝试发送多个请求,因此,假设您决定取消该过程时,可能已经有多个请求发送到服务器,并且所有请求都将发送给服务器。变成等待一秒钟,因此您可能会如上所述等待10或15秒。