0

我在获取此代码块的工作时遇到问题(对于长度感到抱歉)。该代码被消毒以显示相关部分来诊断问题。获取多线程以在网页和业务层之间进行同步

从控制台应用程序运行时,它工作正常。 但是,当从ASP.NET应用程序调用Utlities.SendBulkEmail时,BulkEmailCompleted例程永远不会触发,正是这个例程增加了m_CompletedWorkers计数器。

如何重构SendBulkEmail例程以使用AsyncOperationManager而不是BackgroundWorker,因此我可以保证返回结果的线程。

SendBulkEmail例程本身不是多线程的。多线程发生在它的foreach循环中。

我认为原代码的基础上,从该网站得到: http://www.dotnetfunda.com/articles/article613-background-processes-in-asp-net-web-applications.aspx

的公用事业项目的各种解决方案之间共享,并且非常独立。

我希望我能说清楚。

任何帮助将不胜感激。

的代码如下:

IN THE网站项目(Control.ascx.cs)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Web.UI.HtmlControls; 
using System.Configuration; 
using <company>.BusinessObjects.Emails; 
using <company>.DataAccessors; 
using <company>.DataObjects; 
using <company>.Enumerations; 
using <company>.Interfaces; 
using <company>.Utilities; 
    ... 
     protected void sendButton_OnClick(object sender, EventArgs e) 
     { 
      ... 
       if (HasBenefits) 
       { 
        ReportingEmails emailer = new ReportingEmails(); 
        ... 
        //Prevent send if nothing selected 
        if (... > 0) 
        { 
         List<EmailOutcome> results = emailer.GenerateNotificationEmailsForEmployer(<some int>, <some list>); 
         ... 
        } 
       } 
      ... 
     } 

在业务对象项目

using System; 
using System.Collections.Generic; 
using System.Configuration; 
using System.Linq; 
using System.Net.Mail; 
using System.Resources; 
using System.Text; 
using System.IO; 
using <company>.BusinessObjects.Emails.Helpers; 
using <company>.DataAccessors; 
using <company>.DataObjects; 
using <company>.Enumerations; 
using <company>.Utilities; 

namespace <company>.BusinessObjects.Emails 
{ 
    public class ReportingEmails 
    { 
     ... 
     public List<EmailOutcome> GenerateNotificationEmailsForEmployer(int employerID, List<int> benefits = null) 
     { 
      ... 
      SendNotificationEmails(List<ReportData>, ref emailSuccessByBenefit, true, benefitsToExclude); 
      return emailSuccessByBenefit; 
     } 

     private void SendNotificationEmails(List<ReporterCommsData> reportData, ref List<EmailOutcome> emailSuccessByBenefit, bool isFleet, List<int> benefitsToExclude) 
     { 
      Dictionary<int, MailMessage> bulkEmails = new Dictionary<int, MailMessage>(); 

      //build up the set of emails to send 
      foreach (ReporterCommsData report in reportData) 
      {     
       ... 
       if (String.IsNullOrEmpty(report.Email)) 
       { 
        ... 
       } 
       else 
       { 
        try 
        { 
         MailMessage email = null; 
         ... 
          email = ConstructEmail(<param>, out <param>, <param>); 
         ... 
         bulkEmails.Add(report.BenefitID, email); //add each email to the bulk email dictionary 
         ... 
        } 
        catch (Exception ex) 
        { 
         ... 
        } 
       } 
      } //end foreach 

      //do the bulk email send and get the outcomes 
      try 
      { 
       ... 
       emailSuccessByBenefit.AddRange(Utilities.Mail.SendBulkEmail(bulkEmails, credentials)); 
      } 
      catch (Exception ex) 
      { 
       ... 
      } 
     } 
     ... 
    } 
    ... 
} 

在公用事业PROJECT

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Net.Mail; 
using System.Threading; 

namespace <company>.Utilities 
{ 
    ... 
    public class Mail 
    { 
     private static List<EmailOutcome> m_MultithreadedEmailSendResults = new List<EmailOutcome>(); 
     private static int m_CompletedWorkers = 0; 
     ... 
     /// <summary> 
     /// Sends a large number of emails asynchronously and then reports success of the individual items collectively 
     /// </summary> 
     /// <param name="emails">A dictionary of completed MailMessage objects to send out, keyed on an ID</param> 
     /// <param name="credentials">Network credentials which may be required to send the email</param> 
     /// <returns>List of EmailOutcome objects signifying the success or failure of sending each individual email</returns> 
     public static List<EmailOutcome> SendBulkEmail(Dictionary<int, MailMessage> emails, System.Net.NetworkCredential credentials = null) 
     { 
      const int NUMBER_OF_THREADS_PER_PROCESSOR = 1; 
      m_CompletedWorkers = 0; 

      List<EmailOutcome> results = new List<EmailOutcome>(); 
      List<Dictionary<int, MailMessage>> splitEmailList = new List<Dictionary<int, MailMessage>>(); 
      ... 
      List<BackgroundWorker> workerThreads = new List<BackgroundWorker>(); 

      foreach (Dictionary<int, MailMessage> splitEmails in splitEmailList) 
      { 
       // Initialise the parameter array 
       Object[] parameterArray = new Object[2]; 
       parameterArray[0] = splitEmails; 
       parameterArray[1] = credentials; 

       // Runs on function startup 
       BackgroundWorker worker = new BackgroundWorker(); 
       worker.DoWork += new DoWorkEventHandler(BulkEmailWorker); 
       worker.WorkerReportsProgress = false; 
       worker.WorkerSupportsCancellation = true; 
       worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BulkEmailCompleted); 

       //Add worker to collection 
       workerThreads.Add(worker); 

       //Calling the BulkEmailWorker asynchronously 
       worker.RunWorkerAsync(parameterArray); 
      } 

      //Hold until all background workers complete 
      while (workerThreads.Count > m_CompletedWorkers) 
      { 
       Thread.Sleep(500); //Wait a half second 
      } 

      //Dispose of BackgroundWorkers 
      foreach (BackgroundWorker worker in workerThreads) 
      { 
       worker.Dispose(); 
      } 

      //Get results 
      results.AddRange(m_MultithreadedEmailSendResults); 

      //Clear the static variable 
      m_MultithreadedEmailSendResults.Clear(); 
      m_MultithreadedEmailSendResults = new List<EmailOutcome>(); 

      return results; 
     } 
     ... 

     /// <summary> 
     /// Event handler for the RunWorkerCompleted event. Adds the EmailOutcome results to the static 
     /// </summary> 
     private static void BulkEmailCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      BackgroundWorker worker = sender as BackgroundWorker; 
      //Add the EmailOutcome objects to the static list of results if completed 
      if (worker != null) 
      { 
       Thread.Sleep(200); 
       worker.RunWorkerAsync(); 
      } 
      else 
      { 
       m_MultithreadedEmailSendResults.AddRange(e.Result as List<EmailOutcome>); 
       m_CompletedWorkers++; 
      } 
     } 
     ... 
    } 
    ... 
} 
+0

你有没有试过调试它,并遵循它在做什么的步骤?那将是你最好的选择。 – Zipper 2013-03-20 03:18:10

+0

是的,我试过调试。这就是我知道公用程序项目中的BulkEmailCompleted甚至没有运行的原因。我认为BulkEmailWorker会报告不同的线程或其他内容,因为RunWorkerCompletedEventHandler在作业完成时似乎没有被触发。 – user1058946 2013-03-20 05:39:02

回答

0

w ay asp.net的工作原理是它为每个请求创建一个Page对象。控制也是一样。您发送的电子邮件通知只能访问此对象。

您创建的线程将运行它们的时间来执行,并且您的响应不会等待电子邮件发送完成。这意味着您无法使用相同请求发送状态。

但是,如果您从页面发出另一个请求,ajax或其他内容以获取更新状态,则会创建一个新页面和相应的控件对象。您必须从静态对象获取状态并使用它来向用户显示状态。

您可能会发现UpdatePanel控件方便实现ajax。

相关问题