Feedback
thread分为工作者线程和IO线程把
所以应该让IO线程等待,不会长时间block worker thread,
能够提高throughput
简单讲
异步就是发 Email 请人家办事
同步就是打电话
想想你是办事的人,发Email 处理的case多,还是接电话处理的case多
case 多事一个因素
质量呢?
To montaque
嗯,但是 ThreadPool.QueueUserWorkItem这样使用也无法确定从线程池中取回的线程就是IO线程。
--引用--------------------------------------------------
montaque: 简单讲
异步就是发 Email 请人家办事
同步就是打电话
想想你是办事的人,发Email 处理的case多,还是接电话处理的case多
case 多事一个因素
质量呢?
--------------------------------------------------------
不明白是什么意思?
我的理解是:这样的异步模型,你可以在BeginProcessRequest的时候,给用户一个友好的界面,告诉他系统正在处理他的请求,而使用同步的方式,请求完全被阻塞,浏览器一直在等待或者处于假死状态,用户的请求将得不到任何反馈。
我觉得,其实这个吞吐量就是并发量.
如果原来都是一个线程来完成整个用户请求的始末。
现在就是象一个生产者消费者的关系模型。 也是一个队列的模型
生产者就是接受用户的请求,然后他只负责将任务入队到消费者线程池等待的队列中,
实际的工作量没有变, 但不会因为前台的高并发,导致生产者忙碌。
--引用--------------------------------------------------
Cheese: 我的理解是:这样的异步模型,你可以在BeginProcessRequest的时候,给用户一个友好的界面,告诉他系统正在处理他的请求,而使用同步的方式,请求完全被阻塞,浏览器一直在等待或者处于假死状态,用户的请求将得不到任何反馈。
--------------------------------------------------------
这个异步处理全部是在服务器端,没有仍然客户端的东西。如果你要想浏览器不处于等待或者处于假死状态,那么你可以使用Ajax的异步。
这个是服务器端的异步处理,Asp.net的异步处理的目的就是提高服务器的吞吐量
多谢楼主的提醒,那是否可以这样理解:
不是所有的请求都需要5秒的处理时间,有些请求可能很快就完成了,这个异步就是为了不阻塞那些很快完成的请求,这样一来吞吐量就提高了。
--引用--------------------------------------------------
静静的黎明tm: 我觉得,其实这个吞吐量就是并发量.
如果原来都是一个线程来完成整个用户请求的始末。
现在就是象一个生产者消费者的关系模型。 也是一个队列的模型
生产者就是接受用户的请求,然后他只负责将任务入队到消费者线程池等待的队列中,
实际的工作量没有变, 但不会因为前台的高并发,导致生产者忙碌。
--------------------------------------------------------
你的这个解释是正确的,也没有问题。
现在的问题的,ThreadPool同样使用的处理请求的线程池的线程,使用基于委托的异步同样也是使用了处理请求的线程池中的线程,这样无法提高服务器的并发能力。
呵呵,看来楼主是没有搞清楚windows io机制。
问题在这里:
Thread.Sleep(5000);//模拟IO
这个和IO是有区别的。从线程角度这样是模拟很长的CPU操作(线程并没有被释放,虽然不占CPU),不是模拟IO操作。简单说:Thread A通过BeginXXX进行异步,那么正如楼主说所讲,Thread A释放了,但肯定XXX callback需要在Thread B上进行的,如果XXX是CPU型操作,对系统吞吐量并没有好处;但如果XXX是IO的(比如:netstream.beginread),这时Thread A释放了,但Thread B不会马上创建,只有真正IO上有数据的时候,才会创建,也就是说,等待IO的这段时间没有等待的Thread(由windows的IOCP支持,通过少量的IO Thread同时处理大量的IO任务)。Worker Thread只在BeginIO前,和Callback时占用,在BeginIO和Callback之间的时间是交给IO Thread来负责的。这样ThreadPool就可以通过少量的Worker Thread处理大量的请求,前提条件是这些请求是block在IO上的。
不知道说清楚没有。如果我理解不对也欢迎指出!
--引用--------------------------------------------------
weidagang2046
你说得非常正确,我正是在这儿理解有些问题,在IO时,这个时候可以不用线程等待,由Windows的IOCP支持。
但是
public void StartAsyncWork()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), null);
}
private void StartAsyncTask(Object workItemState)
{
Thread.Sleep(5000);//模拟IO ,这个可以不占用线程,线程没有阻塞
....}
不知道你注意没有,代码在IO操作前,都已经ThreadPool.QueueUserWorkItem,已经从线程池中获取了一个线程了。
可能是我对ASP.net异步处理机制还理解不够,不知道具体何时交出占用的线程,何时从线程池中取回线程
--引用--------------------------------------------------
不知道你注意没有,代码在IO操作前,都已经ThreadPool.QueueUserWorkItem,已经从线程池中获取了一个线程了。
可能是我对ASP.net异步处理机制还理解不够,不知道具体何时交出占用的线程,何时从线程池中取回线程
--------------------------------------------------------
交出线程很简单,何时return何时交出。调用.net framework定义的BeginIO,比如:netstream.beginread, xxx.beginrequest就会利用iocp,但还是需要你return才行,如果你beginread以后,再sleep一会儿,线程依然不会释放。取回线程的时机是由.net framework根据iocp的事件决定的,这时会从ThreadPool取一个线程来调用callback。
“Worker Thread只在BeginIO前,和Callback时占用”这句话不对,更正:“worker thread在begin io后释放(如果beginio后代码return),直到callback时再占用worker thread”
使用了异步模式,接受的请求数量增加,排队处理的内容就多了,然后cpu使用率提高了,吞吐率就高了。在不使用异步时,cpu的使用率相对就低。
--引用--------------------------------------------------
rosanshao: --引用--------------------------------------------------
--------------------------------------------------------
你的这个解释是正确的,也没有问题。
现在的问题的,ThreadPool同样使用的处理请求的线程池的线程,使用基于委托的异步同样也是使用了处理请求的线程池中的线程,这样无法提高服务器的并发能力。
--------------------------------------------------------
突然想到一个很好的例子, 去过卖当劳吧, 前面的收银就是我说的生产者, 他把客人的请求接受完,就交给了后面给客人配食品的的, 然后受理下一个客人。
而实际上假设客人再多, 后面负责给客人备食品的服务员不用很多人。
重点就是,如果是用线程池和异步。 线程池里用很少数量的线程,就可以应对大并发的后续处理请求。
因为 "高并发, 极短处理时间" 的这种请求类型,非常适合使用用异步 + 线程池来完成。后台只需很少的线程就能完成高并发的处理,因为每个请求的处理时间太短了。
使用类似windows完成端口这种机制你会发现在高并发情况下,你的线程数量少得让你惊讶。
LZ似乎忘记了,创建进程、线程等也是需要花费时间的
--引用--------------------------------------------------
DonLiang: LZ似乎忘记了,创建进程、线程等也是需要花费时间的
--------------------------------------------------------
创建进程、线程等也是需要花费时间的,这是肯定的
使用异步,要看情况,对于需要在服务长时间处理的,如果基本Http长连接的即
时消息传送
--引用--------------------------------------------------
静静的黎明tm: --引用
--------------------------------------------------------
你提到的,原理大家都应该是很清楚的。其实真正的问题是在给客人配食品的与
后面给客人配食品的是如何区分的。
也就是BeginProcessRequest与
public void StartAsyncWork()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), null);
}
执行StartAsyncTask方法的线程是否都是处理请求的线程,如果是的话,那么显然不得提高并发能力
经过几天的测试,终于得到答案,无论是使用基本委托的异步(实质也是使用了线程池中的线程)还是使用线程池,
都无法提高服务器的并发能力,唯一能够提高的办法,就是自定义一个线程池。
记得以前看到自定义线程池的实现,如有知道的,麻烦告知一下。谢谢各位了。
不懂不要乱说.
要明白ASP.NET的异步模式, 先把WINSOCK的CP的超高并发量的原理弄懂先.