防止多线程网站消耗太多资源

时间:2012-03-09 08:13:05

标签: asp.net multithreading performance iis-7.5 parallel-processing

我为客户建立了一个批量电子邮件发送网站,需要在一次发送中发送80,000封电子邮件。它基本上为发送创建了一个新线程,以便可以将控制权交还给UI(以便反馈页面可以加载),然后为每个公司创建一个新线程,以便向其收件人发送电子邮件。所有电子邮件都使用以下代码排队:

// Loop through the companies and send their mail to the specified recipients
        // while creating a new thread for each company
        // A new thread is started so that the feedback page can load
        SendingThread = Task.Factory.StartNew(() =>
        {
            // This is a thread safe for loop
            Parallel.ForEach<CompanyEntity>(companies, company =>
            {
                    // Start a new thread for each company send
                    Task.Factory.StartNew(() =>
                    {
                        // Get the recipients for this company
                        var companyRecipients = GetSubscribersForCompany(company.Id, recipients);

                        // Send the newsletter to the company recipients
                        var success = SendNewsletterForCompany(newsletter, company, companyRecipients, language,
                                                               version, company.AdvertCollectionViaNewsletterCompanyAdvertLink, newsletter.NewsletterType, email);

                        // Add the status update so the front end can view a list of updated conpany statuses
                        if (success)
                            AddStatusUpdate(company.CompanyTitle + " has completed processing.");

                        // Starts sending the emails if the engine hasn't already been started
                        SendEngine.Start(CurrentSmtpClient, this);

                    }).ContinueWith(antecendent => EndCompaniesSendUpdate(companiesToProcess, companiesProcessed), TaskContinuationOptions.OnlyOnRanToCompletion);
            });
        }, new CancellationToken(), TaskCreationOptions.LongRunning, TaskScheduler.Default);

当电子邮件排队时,发送引擎接管并从队列中提取电子邮件,然后使用新的Parallel类发送它们:

Action action = () =>
        {
            MailMessage message;
            while (queue.TryDequeue(out message))
            {
                SendMessage(sendingServer, message, factory);
            }
        };

        // Start 5 concurrent actions to send the messages in parallel.
        Parallel.Invoke(action, action, action, action, action);

所有这些都很有效,可以在大约10分钟内发送40,000条简报。唯一的问题是服务器上的RAM和CPU在这10分钟内消耗了100%。这会影响服务器上的其他站点,因为它们无法访问。

有没有办法在IIS 7.5中限制发送应用程序的资源使用情况,或者更改上面的代码?

1 个答案:

答案 0 :(得分:2)

<强>问题:

  • 你正在Parallel ForEach中生成一个线程,“Parallel”部分意味着它已经为身体产生了一个线程。您正在另一个Action内部并行调用而不是并行ForEach中的Action。

  • 您正在线程内部运行while循环而没有CPU休息。这是并行调用5x。

<强>数目:

对于CPU使用率,您需要让您的处理喘息一下。在你的While TryDequeue循环中放一个简短的Sleep。

        MailMessage message;
        while (queue.TryDequeue(out message))
        {
            SendMessage(sendingServer, message, factory);
            Thread.Sleep(16);
        }

对于RAM和CPU使用,您需要立即处理LESS。

        SendingThread = Task.Factory.StartNew(() =>
        {
            foreach(var company in companies) 
            {
                        // Get the recipients for this company
                        var companyRecipients = GetSubscribersForCompany(company.Id, recipients);

                        // Send the newsletter to the company recipients
                        var success = SendNewsletterForCompany(newsletter, company, companyRecipients, language,
                                                               version, company.AdvertCollectionViaNewsletterCompanyAdvertLink, newsletter.NewsletterType, email);

                        // Add the status update so the front end can view a list of updated conpany statuses
                        if (success)
                            AddStatusUpdate(company.CompanyTitle + " has completed processing.");

                        // Starts sending the emails if the engine hasn't already been started
                        SendEngine.Start(CurrentSmtpClient, this);


            }
       }, new CancellationToken(), TaskCreationOptions.LongRunning, TaskScheduler.Default);