2009-11-19 11 views
8

मुझे कंसोल एप्लिकेशन के माध्यम से ईमानदारी से ईमेल भेजने की आवश्यकता है। मुझे कॉलबैक पर कुछ डीबी अपडेट करने की ज़रूरत है लेकिन कॉलबैक कोड चलाने से पहले मेरा आवेदन बाहर निकल रहा है!SmtpClient.SendAsync - कॉलबैक ट्रिगर होने से पहले बाहर निकलने वाले एप्लिकेशन को कैसे रोकें?

अनुमान अनुमान लगाने से पहले प्रतीक्षा करने में कितना समय लगता है, मैं इसे अच्छी तरह से होने से कैसे रोक सकता हूं। मुझे लगता है कि Async कॉल थ्रेड के किसी रूप में रखा जाता है? क्या यह जांचना संभव है कि कोई कॉल करने का इंतजार कर रहा है या नहीं?

नमूना कोड

private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) 
{ 
    // Get the unique identifier for this asynchronous operation. 
    String token = (string) e.UserState; 
    if (e.Cancelled) 
    { 
     Console.WriteLine("[{0}] Send canceled.", token); 
    } 
    if (e.Error != null) 
    { 
     Console.WriteLine("[{0}] {1}", token, e.Error.ToString()); 
    } 
    else 
    { 
     // update DB 
     Console.WriteLine("Message sent."); 
    } 
} 

public static void Main(string[] args) 
{ 
    var users = Repository.GetUsers(); 
    SmtpClient client = new SmtpClient("Host"); 
    client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); 
    MailAddress from = new MailAddress("[email protected]", "System", Encoding.UTF8); 
    foreach (var user in users) 
    { 
     MailAddress to = new MailAddress(user.Email); 
     MailMessage message = new MailMessage(from, to); 
     message.Body = "This is a test"; 
     message.BodyEncoding = System.Text.Encoding.UTF8; 
     message.Subject = "test message 1" + someArrows; 
     message.SubjectEncoding = System.Text.Encoding.UTF8; 
     string userState = String.Format("Message for user id {0}", user.ID); 
     client.SendAsync(message, userState); 
     message.Dispose(); 
    } 

    // need to wait here until I have received a callback for each message 
    // otherwise the application will exit 
} 

उत्तर

8

बाहर निकलने से पहले एक ManualResetEvent कॉल WaitOne भी इसे बनाएं उस पर। जब अंतिम ईमेल/dbupdate किया जाता है, तो मैन्युअल रीसेट इवेंट पर सेट करें।


public static void Main(string[] args) 
{ 
    object someArrows = ">>>"; 
    var users = Repository.GetUsers(); 
    SmtpClient client = new SmtpClient("Host"); 
    client.SendCompleted += SendCompletedCallback; 
    MailAddress from = new MailAddress("[email protected]", "System", Encoding.UTF8); 
    int numRemaining = users.Length; 
    using(ManualResetEvent waitHandle = new ManualResetEvent(numRemaining == 0)) 
    { 
     object numRemainingLock = new object(); 
     foreach(var user in users) 
     { 
      MailAddress to = new MailAddress(user.Email); 
      MailMessage message = new MailMessage(from, to); 
      try 
      { 
       message.Body = "This is a test"; 
       message.BodyEncoding = System.Text.Encoding.UTF8; 
       message.Subject = "test message 1" + someArrows; 
       message.SubjectEncoding = System.Text.Encoding.UTF8; 
       string userState = String.Format("Message for user id {0}", user.ID); 
       client.SendCompleted += delegate 
       { 
        lock(numRemainingLock) 
        { 
         if(--numRemaining == 0) 
         { 
          waitHandle.Set(); 
         } 
        } 
       }; 
       client.SendAsync(message, userState); 
      } 
      catch 
      { 
       message.Dispose(); 
       throw; 
      } 
     } 
     waitHandle.WaitOne(); 
    } 
} 
+0

हाय क्या आप यह नमूना प्रदान कर सकते हैं कि आप इसे कैसे सलाह देंगे? मैंने आपको एक उदाहरण दिखाने के लिए अपना उत्तर अपडेट किया है – James

+0

आप SendCompleted + = SendCompletedCallback को सेट कर रहे हैं, लेकिन फिर उस लूप में जिसे आप एक प्रतिनिधि को भेजें प्रेषित कर रहे हैं? क्या इसका मतलब है कि प्रतिनिधि कोड चलाया जाता है और फिर SendCompletedCallback को बुलाया जाता है? – James

+0

हाँ। लेकिन ध्यान दें, ऑर्डरिंग जिसमें कॉलबैक कहा जाता है, की गारंटी नहीं है। इसलिए, SendCompleted या तो SendCompletedCallback 1 या मेरे प्रतिनिधि 1 को कॉल कर सकता है। –

संबंधित मुद्दे

 संबंधित मुद्दे