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。