2011-08-30 85 views
3

我想在IIS中开始使用异步处理。编辑:我正在谈论使用任务并行库。在IIS中使用线程的特殊注意事项

例如,在某些页面加载时,我想记录一堆废话,发送电子邮件,更新某些表格等,但我不想让用户等待我记录所有这些废话。

所以通常我所做的是我有一个静态队列,我将日志信息推入,然后我有一个cron作业,每10分钟调用一次其OnLoad刷新队列的特殊页面。这很有用,但它的设置很笨重,特别是当你想记录50件事情时。我宁愿这样做:

Task.CreateNew(() => Log(theStuff)); 

不过,我很害怕在IIS中运行的任务,因为一个滑起来,你的整个网站的下降。

所以现在我有

SafeTask.FireAndForget(() => Log(theStuff)); 

此包装的委托在一些try/catch语句,并将其传递到Task.CreateNew。所以如果有人改变了一些影响其他事情的东西,而这些东西会在别的地方产生一个意外地被抛出的任何异常,我们会收到一个通知,而不是崩溃的网站。此外,catch内部的错误通知也在它自己的try/catch中,而catch的catch也会尝试以不同的方式尝试登录。

现在我可以安全地在IIS中异步运行东西,什么其他我需要担心的事情之前,我可以开始使用我的SafeTask类?

+0

在IIS中使用线程时要小心。 IIS已经使用线程来处理各个请求,并且可用的总数有一个限制。 –

+0

@joel我可以为此创建新线程,所以我不惹IIS限制? – dan

+0

这是一个操作系统的限制,而不是IIS限制 –

回答

1

默认情况下,IIS和.net中的每个请求都在一个线程中处理。该线程来自称为“应用程序池”的线程池。现有的线程被重用,所以除非每次清除或设置它,否则你不能真正将它们用于线程状态。您可以使用machine.config中的MSDN公式甚至web.config来定义此线程池的大小。

现在,每个异步函数调用放在不同的线程。这包括异步Web服务调用,异步页面函数,异步委托等。此线程来自“应用程序池”,从而减少了可用于IIS的线程数量以处理新的请求。

很可能,您的应用程序在使用异步函数调用时会很好地工作。如果您担心或者您有很多异步任务,那么您可能需要创建自己的线程池或查看codeplex上的SmartThreadPool。

希望这会有所帮助。

+0

如果不是使用ThreadPool.QueueUserWorkItem和等价物,我使用TaskParallelLibrary,它保留作业的内部队列并设置线程数量? – dan

+0

线程总是来自同一个应用程序池 - 对于IIS托管的应用程序,它们来自IIS中的应用程序池,以及自托管或控制台/ Windows应用程序,它们来自您自己的应用程序池,默认情况下它是由.net为您创建的。这是因为线程池与进程相关联。因此,任务并行库将从您的线程池中消耗与您的应用程序相同的线程。 – Nabheet

+0

谢谢,我误解了,并认为任务有他们自己的池,只限于几个线程... – dan

1

考虑使用页面的OnUnload事件。在此处阅读:http://msdn.microsoft.com/en-us/library/ms178472.aspx

此事件在内容发送给用户后触发(因此用户在您工作时未被阻止),并且应完全满足您的需求而不引入其他线程。

针对你的问题,只有当你的负载和性能测试表明你运行的是线程限制时,你才应该关注线程池耗尽。如果你不是,那么你提出的建议肯定是合理的。

+0

嗯,这很有趣,但是很多这种事情发生在App_Code的深处。我想我可以将所有的日志对象添加到HttpContext Items集合中,但是我可以使用这个全局等效的页面卸载吗? – dan