为什么 asnyc await 可以提高web程序的吞吐量

(转网上一段话)

Web程序天生就是多线程的,且web线程都是跑的线程池线程(使用线程池线程是为了避免不断创建、销毁线程所造成的资源成本浪费),而线程池线程可使用线程数量是一定的,尽管可以设置,但它还是会在一定范围内。如此一来,我们web线程是珍贵的(物以稀为贵),不能滥用。用完了,那么其他用户请求的时候就无法处理直接503了。

那什么算是滥用呢?比如:文件读取、URL请求、数据库访问等IO请求。如果用web线程来做这个耗时的IO操作那么就会阻塞web线程,而web线程阻塞得多了web线程池线程就不够用了。也就达到了web程序最大访问数。

此时我们的新异步 async await 横空出世,解放了那些原本处理IO请求而阻塞的web线程(想偷懒?没门,干活了。)。通过异步方式使用相对廉价的线程(非web线程池线程)来处理IO操作,这样web线程池线程就可以解放出来处理更多的请求了。

测试代码:

    public class TestAsyncController : ApiController
    {
        public async void Test(string id)
        {
            try
            {
                Trace.WriteLine("before the await,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                await GetData(id);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex);
            }
            Trace.WriteLine("after the await,the thread id id " + Thread.CurrentThread.ManagedThreadId);
            Trace.WriteLine("");
        }


        public Task GetData(string id)
        {
            if (id == null)
            {
                throw new Exception("抛个异常试试!");
            }
            Trace.WriteLine("before task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
            var tk = Task.Run(() =>
            {
                Trace.WriteLine("in the task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                Trace.WriteLine("sleep 3 秒");
                Thread.Sleep(3000);
                Trace.WriteLine("sleep end");
            });
            Trace.WriteLine("after task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
            return tk;
        }
    }

 

 

可以看出来, before the await 和 after the await 后的线程ID不一样,说明执行到GetData()方面里面的Task时,web线程就被解放出来了.

如果去掉async 和 await ,在GetData() 方法里面加上 Task.WaitAll(tk) 结果会是什么呢?

        public void Test(string id)
        {
            try
            {
                Trace.WriteLine("before the await,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                GetData(id);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex);
            }
            Trace.WriteLine("after the await,the thread id id " + Thread.CurrentThread.ManagedThreadId);
            Trace.WriteLine("");
        }


        public Task GetData(string id)
        {
            if (id == null)
            {
                throw new Exception("抛个异常试试!");
            }
            Trace.WriteLine("before task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
            var tk = Task.Run(() =>
            {
                Trace.WriteLine("in the task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                Trace.WriteLine("sleep 3 秒");
                Thread.Sleep(3000);
                Trace.WriteLine("sleep end");
            });
            Task.WaitAll(tk);
            Trace.WriteLine("after task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
            return tk;
        }

结果如下:

before the await 和 after the await 的线程ID 永远一样.说明web线程是一样的

posted @ 2018-03-03 19:50  热敷哥  阅读(343)  评论(0编辑  收藏  举报