C# rest api中的Thread.sleep与Task.delay

C# rest api中的Thread.sleep与Task.delay,c#,.net,multithreading,azure,async-await,C#,.net,Multithreading,Azure,Async Await,我比较了Thread.sleep和task.delay。从数据库检查作业完成状态。作业将由其他Azure组件执行 为了测试它,创建了带有同步和异步模式的小型api 使用异步的http rest api: public async Task<HttpResponseMessage> Post() { await Task.Delay(200); return await Task.FromResult(new HttpResponseMessage());} 有趣的是

我比较了Thread.sleep和task.delay。从数据库检查作业完成状态。作业将由其他Azure组件执行

为了测试它,创建了带有同步和异步模式的小型api

使用异步的http rest api:

public async Task<HttpResponseMessage> Post()
{
    await Task.Delay(200);
    return await Task.FromResult(new HttpResponseMessage());}
有趣的是。对于同步调用,结果很好。使用ApacheJMeter对100个用户进行了5次迭代

同步结果:分钟:414毫秒平均:8464毫秒

异步结果:最小1756毫秒平均值:10044毫秒


为什么Thread.sleep比Async好。这是任务创建的开销吗?我不能得到比这两个更好的结果吗?

异步代码的目的不是提高单个操作的性能。事实上,正如你所看到的,有时候恰恰相反


异步代码的要点是不锁定当前线程。好处取决于应用程序的类型:

桌面应用程序(我知道这不适用于你,但值得一提)

在桌面应用程序中,您不会冻结UI线程。这样,当您等待来自某个I/O操作的响应时,您的UI将保持对用户的响应

因此,虽然单个操作可能需要稍长的时间,但用户不会因为UI没有冻结而感到沮丧

网络应用程序

在web应用程序中,它释放当前线程来处理下一个传入的请求。ASP.NET可使用的线程数量有限,因此,如果您的流量足够繁忙,请求可能必须等待处理。异步代码可以帮助您避免这种情况

例如,同步I/O操作将锁定当前线程(如
thread.Sleep
)。在操作完成之前,线程不能执行任何其他操作

如果使用异步代码(如
Task.Delay
),那么一旦异步操作启动,线程将返回到线程池,并可用于在等待时处理另一个请求

所以,虽然单个操作可能需要稍长的时间,但它允许应用程序处理更大的负载


微软在这方面的文档非常优秀:

异步并不是为了降低延迟而设计的-有很多基础设施,所以与更多的“裸骨”调用相比,更高的延迟是可以预期的。顺便说一句,“更好的结果”是什么意思还不清楚。您可以将代码简化如下:
returnnewhttpresponsemessage()
-无需等待任务。FromResult异步代码的要点是异步执行某些东西,而不是按照严格预测的顺序执行。它可以释放螺纹,也可以是单螺纹。异步I/O的要点是将I/O操作卸载到特定的基础设施,从而释放CPU资源,但这只是异步代码适用性的一个示例。而
Thread.Sleep
与I/O无关。“而
Thread.Sleep
与I/O无关。”-是的,我知道。但在这个问题中,
Thread.Sleep
Task.Delay
被用作同步和异步I/O操作的占位符。出于这个目的,它们是有效的。不,它们不是,因为它们与底层的I/O操作有着完全不同的性质,所以将它们作为I/O的替代品进行测试是不公平的,并以这种方式对待它们。这不是一个完美的替代品,不。但根据我的经验,在观察异步函数和非异步函数的行为方式之间的差异时,它们非常有用。这个问题就是一个很好的例子,如果我们不是专门讨论I/O操作(不仅仅是广泛的异步操作),那么使用异步I/O的主要目标就是可伸缩性。这种质量属性的差异(在同步与异步的情况下)是不可测量的,并且在使用任何异步I/O替代的情况下是不可观察的。因此,虽然它们可以用于测量任何其他差异,但它们可以被替代,但正如您所说,它们是I/O这种测量的占位符,至少是不公平的,最坏的情况是没用。
public HttpResponseMessage Post()
{
    Thread.sleep(200);
    return new HttpResponseMessage();}