等待Task.Delay;真的让Web服务器能够处理更多的同步请求吗?

时间:2014-05-29 17:18:10

标签: asp.net-mvc task async-await

使用.Net 进行 Pro Asynchrnous编程:

    for (int nTry = 0; nTry < 3; nTry++)
    {
        try
        {
            AttemptOperation();
            break;
        }
        catch (OperationFailedException) { }
        Thread.Sleep(2000);
    }
     

在休眠时,线程不消耗任何基于CPU的资源,   但线程存活的事实意味着它仍然在消耗   内存资源。在桌面应用程序上,这可能不大   处理,但在服务器应用程序上,有很多线程在休眠   不理想,因为如果更多的工作到达服务器,它可能必须   旋转更多线程,增加内存压力并增加额外的内存   操作系统要管理的资源。

     

理想情况下,您不希望将线程置于睡眠状态   简单地放弃,让线程可以自由地为其他人服务   要求。当您准备好再次继续使用CPU资源时   你可以获得一个线程(不一定是同一个)并继续   处理。您可以通过不将线程放入来解决此问题   睡觉,而是使用等待被认为完成的任务   在一定时期内。

    for (int nTry = 0; nTry < 3; nTry++)
    {
        try
        {
            AttemptOperation();
            break;
        }
        catch (OperationFailedException) { }
        await Task.Delay(2000);
    }

我不遵循作者的推理。虽然调用await Task.Delay确实会释放这个线程(处理请求),但Task.Delay创建的任务也会占用其他一些线程来运行。那么这段代码真的能让服务器处理更多的同步请求,或者文本错误了吗?!

1 个答案:

答案 0 :(得分:9)

Task.Delay不会占用其他一些帖子。它为您提供无阻塞的任务。它启动一个计时器,在其回调中完成该任务。等待时,计时器不使用任何线程。

像延迟或IO这样的异步操作只是将工作推送到另一个线程,这是一个常见的神话。他们不。它们使用OS工具在操作正在进行时真正使用零线程。 (他们显然需要使用一些线程来启动和完成操作。)

如果异步只是将工作推送到另一个线程,那么它几乎是无用的。它的价值只是让UI在客户端应用程序中保持响应。在服务器上它只会造成伤害。事实并非如此。

async IO的值是减少内存usag(减少线程堆栈),上下文切换和线程池利用率。

您发布的代码的异步版本将扩展到数万个并发请求(如果您适当地增加ASP.NET限制,这是一个简单的web.config更改),内存使用量很少。