Dre*_*kes 8 .net iis asynchronous threadpool
我的网站用户执行的某些操作会导致发送电子邮件.发送电子邮件的代码可能会阻塞一段时间,所以我想从他们的HTTP请求处理程序的线程中执行此操作.
目前我正在使用类似的东西:
ThreadPool.QueueUserWorkItem(o => {
try
{
email.Send();
}
catch (Exception ex)
{
_log.Error("Error sending email", ex);
}
});
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,这是有效的.但是,该网站在托管环境中运行,可以回收应用程序池.
每隔一段时间我都不会收到应该发送的电子邮件,我怀疑在应用程序池回收期间,线程池队列中的这个工作项被删除了.
如何执行这样的ansync操作并保证在这种情况下完成?
如果应用程序以集成模式运行,则可以在主机环境中注册邮件分派器服务.主机将在回收完成之前通知您的服务.它将执行2次调用IRegisteredObject.Stop.在第一次通话时,主持人为您提供完成工作的机会.如果达到超时且您的服务未从主机上移除,则进行另一次呼叫,但这次仅通知在有或没有服务同意的情况下进行回收.
这是一个如何实现Stop()方法的示例(未测试):
public class MailDispatchService : IRegisteredObject
{
private AutoResetEvent _processQueueEvt = new AutoResetEvent();
private ConcurrentQueue<MailMessage> _queue = new ConcurrentQueue<MailMessage>();
private Thread _dispatcherThread;
private volatile bool _enabled = true;
#region Implementation of IRegisteredObject
public void Stop(bool immediate)
{
if (_dispatcherThread != null && _dispatcherThread.IsAlive)
{
// is not a immediate stop, we can wait for the queue to empty
if (!immediate)
{
// stop to accept new requests...
_enabled = false;
// awake dispatcher thread, so it can quit if the queue is empty
_processQueueEvt.Set();
// and wait for a while but not forever.
_dispatcherThread.Join(TimeSpan.FromSeconds(30));
}
else
{
// host env will recycle now, nothing to do
_dispatcherThread.Abort();
}
}
// remove the service from host
HostingEnvironment.UnregisterObject(this);
}
#endregion
public void Start()
{
_dispatcherThread = new Thread(ProcessQueue);
_dispatcherThread.Start();
}
private void ProcessQueue()
{
while (_enabled)
{
_processQueueEvt.WaitOne();
MailMessage message;
while (_queue.TryDequeue(out message)) { /* send mail ...*/}
}
}
public void DispatchEmail(MailMessage message)
{
if (!_enabled) throw new Exception("....");
_queue.Enqueue(message);
_processQueueEvt.Set();
}
}
Run Code Online (Sandbox Code Playgroud)
启动服务并在主机上注册.
var mailService = new MailDispatchService();
System.Web.Hosting.HostingEnvironment.RegisterObject(mailService);
mailService.Start();
var message = new MailMessage();
mailService.DispatchEmail(message);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1342 次 |
| 最近记录: |