我在獲取此代碼塊的工作時遇到問題(對於長度感到抱歉)。該代碼被消毒以顯示相關部分來診斷問題。獲取多線程以在網頁和業務層之間進行同步
從控制檯應用程序運行時,它工作正常。 但是,當從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++;
}
}
...
}
...
}
你有沒有試過調試它,並遵循它在做什麼的步驟?那將是你最好的選擇。 – Zipper 2013-03-20 03:18:10
是的,我試過調試。這就是我知道公用程序項目中的BulkEmailCompleted甚至沒有運行的原因。我認爲BulkEmailWorker會報告不同的線程或其他內容,因爲RunWorkerCompletedEventHandler在作業完成時似乎沒有被觸發。 – user1058946 2013-03-20 05:39:02