【问题标题】:Why does my IIS application pool shutdown after throws and exception by worker thread while using multi threads?为什么我的 IIS 应用程序池在使用多线程时被工作线程抛出和异常后关闭?
【发布时间】:2020-08-26 23:52:04
【问题描述】:

我正在尝试创建一些电子邮件发送过程。如果没有多线程方法,它可以按预期工作。但是发送所有电子邮件需要更多时间。

在我决定使用多线程之后,我也为多线程进程做了一些异常处理。

这是我的方法,

public enum EmailRequestProcesStatus
{
    Pending = 1,
    Processing = 2,
    Complete = 3
}
public async Task<int> InvokeSendingEmailAsync(string serverFolderPath)

{
            // update pending requests
            await UpdateEmailRequestToProcessAsync(EmailRequestProcesStatus.Processing);

            var invokedDateTime = DateTime.Now;
            // first get the CustomerEmail list
            var emailList= await GetPendingEmailList();

            IList<CustomerRule> customerRules = new List<CustomerRule>();
            int ruleLength = 0;
            List<Thread> threadList = new List<Thread>();
            // email count list
            List<int> sendEmailCountList = new List<int>();

            foreach (var customer in emailList)
            {
                ruleLength++;
                customerRules.Add(customer);
                if (ruleLength % 20 == 0)
                {
                    var custList = customerRules;
                    Thread t = new Thread(() => ProcessEmailSend(custList, serverFolderPath, invokedDateTime, sendEmailCountList));
                    threadList.Add(t);
                    t.Start();
                    customerRules = new List<CustomerRule>();
                }
            }

            if (customerRules.Count > 0)
            {
                Thread t = new Thread(() => ProcessEmailSend(customerRules, serverFolderPath, invokedDateTime, sendEmailCountList));
                threadList.Add(t);
                t.Start();
            }

            // join the all threads
            foreach (var thread in threadList)
            {
                thread.Join();
            }

            return sendEmailCountList.Count;
}

private void ProcessEmailSend(IList<CustomerRule> customerList, string serverFolderPath, DateTime invokedDateTime, List<int> sendEmailCountList)
{
   foreach(var cust in customerList)
   {
       var customerDetailList = get customerEmailDetails(cust);

       // access some file from file server by giving details
       var result = getPdf(customerDetailList.files);

       // do the rest of work using 
   }
}

private filesDto getPdf(filesDto files)
{
   try
   {
      //here I call the file server 
   }
   catch(Exception e)
   {
       UpdateEmailServiceWhenException();
       throw;
   }
}

throw 后会被全局异常处理程序捕获。 如果一个工作线程从文件服务器中发现文件未找到的异常,则它作为异常插入到表中并再次抛出。

从此,所有进程都将终止,IIS 应用程序池也将关闭。表中也可能有不明确的多条记录。

如何排序?

【问题讨论】:

  • 应用程序池回收、断电,各种事情都可能导致进程突然退出,即使在受控情况下,asp.net 也不知道您的线程。最好在某处(数据库、消息队列等)对电子邮件进行排队,然后让非 asp-net 的东西从该队列中拉取电子邮件请求并可靠地发送电子邮件
  • @Damien_The_Unbeliever 感谢您的评论。使用队列可以像拥有多个线程一样获得性能提升。如果没有多线程,我不会出现这个错误。
  • 你可能会觉得这很有趣:Fire and Forget on ASP.NET

标签: c# multithreading exception iis


【解决方案1】:

最有可能的是,在该工作线程中抛出多个未处理的异常会导致快速失败保护功能。
https://docs.microsoft.com/en-us/iis/configuration/system.applicationHost/applicationPools/add/failure
简单来说,在可配置的时间跨度内(默认为 5 分钟内 5 个)足够多的未处理异常将关闭 App Pool,导致 503 Service Unavailable 响应。
请检查应用程序池中的高级设置。

为了解决这个问题,我们需要处理异常或防止异常被抛出。
请参考下面的讨论。
Why does my IIS7 application pool shutdown after an exception in a DLL called from an ASP.NET page?

【讨论】:

  • 感谢您的回答。是的,我已经捕获了异常,再次使用 throw 关键字的全部目的是停止我创建的工作线程并加入主线程。有没有其他方法可以做到这一点。如果是这样,我不想在捕获异常后再次抛出它。
猜你喜欢
  • 2017-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-24
  • 1970-01-01
  • 2019-09-14
  • 2021-07-13
  • 2012-11-11
相关资源
最近更新 更多