0

이 코드 덩어리가 작동하는 데 문제가 있습니다 (해당 기간 동안 유감스럽게 생각합니다). 코드는 문제를 진단하는 데 관련된 부분 만 보여주기 위해 소독됩니다.웹 페이지와 비즈니스 계층을 동기화하는 멀티 스레딩 받기

콘솔 앱에서 실행하면 정상적으로 작동합니다. 그러나 Utlities.SendBulkEmail이 ASP.NET 응용 프로그램에서 호출 될 때 BulkEmailCompleted 루틴은 절대로을 실행하지 않으며 m_CompletedWorkers 카운터를 증가시키는 루틴입니다.

SendBulkEmail 루틴을 BackgroundWorker 대신 AsyncOperationManager를 사용하도록 리팩터링하는 방법은 결과가 반환되는 스레드를 보장 할 수 있습니다.

SendBulkEmail 루틴 자체는 멀티 스레드가 아닙니다. 멀티 스레딩은 foreach 루프 내에서 발생합니다. http://www.dotnetfunda.com/articles/article613-background-processes-in-asp-net-web-applications.aspx

Utilities (유틸리티) 프로젝트는 다양한 솔루션 공유하고, 거의 혼자 서있다 :

나는 원래 코드의 기초는이 웹 사이트에서 입수했다 생각합니다.

나는 이것을 분명히하고 싶습니다.

도움이 될 것입니다.

코드는 다음과

웹 사이트 PROJECT IN

(Control.ascx.cs) 유틸리티 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++; 
      } 
     } 
     ... 
    } 
    ... 
} 
IN 비즈니스 오브젝트 PROJECT
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) 
      { 
       ... 
      } 
     } 
     ... 
    } 
    ... 
} 

IN

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>); 
         ... 
        } 
       } 
      ... 
     } 

+0

디버깅 해본 후 수행중인 단계를 따라 해 보셨습니까? 그것은 최선의 방법입니다. – Zipper

+0

예, 디버깅을 시도했습니다. 이것이 내가 유틸리티 프로젝트의 BulkEmailCompleted가 실행되고 있지 않다는 것을 안다. 나는 RunWorkerCompletedEventHandler가 작업이 완료되었을 때 발사하지 않는 것처럼 보이기 때문에 BulkEmailWorker가 다른 스레드 또는 다른 것으로보고하고 있다고 생각합니다. – user1058946

답변

0

w ay asp.net은 요청마다 페이지 객체를 생성합니다. 컨트롤에 대해서도 마찬가지입니다. 보내는 이메일에 대한 알림은이 개체에만 전달할 수 있습니다.

작성한 스레드가 실행될 시간이 걸리므로 응답이 완료 될 때까지 기다리지 않습니다. 즉, 동일한 요청을 사용하여 상태를 보낼 수 없습니다.

그러나 업데이트 된 상태를 얻으려면 아약스 또는 다른 방법으로 페이지를 요청하면 새 페이지와 해당 컨트롤 개체가 만들어집니다. 정적 객체에서 상태를 가져 와서이를 사용하여 사용자에게 상태를 표시해야합니다.

ajax를 구현하려면 UpdatePanel 컨트롤이 편리 할 수 ​​있습니다.