2013-05-08 8 views
7

हमारे पास कुछ (सिंक्रोनस) ईमेल कोड है, जो एक वर्ग बनाता है जो एक SmtpClient बनाता है, और उसके बाद एक ईमेल भेजता है। SmtpClient का पुन: उपयोग नहीं किया जाता है; लेकिन हम हर अब और फिर निम्न अपवाद प्राप्त करें:SmtpClient.Send को कॉल करते समय हमें समय-समय पर "एक असीमित कॉल पहले से प्रगति पर क्यों मिलता है"?

System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.InvalidOperationException: An asynchronous call is already in progress. It must be completed or canceled before you can call this method. 
    at System.Net.Mail.SmtpClient.Send(MailMessage message) 
    at EmailSender.SendMail(MailAddress fromMailAddress, string to, String subject, String body, Boolean highPriority) in ...\EmailSender.cs:line 143 

कोड इस तरह दिखता है:

// ... 
var emailSender = new EmailSender(); 
emailSender.SendMail(toEmail, subject, body, true); 
// emailSender not used past this point 
// ... 

public class EmailSender : IEmailSender 
{ 
    private readonly SmtpClient smtp; 

    public EmailSender() 
    { 
     smtp = new SmtpClient(); 
    } 

    public void SendMail(MailAddress fromMailAddress, string to, string subject, string body, bool highPriority) 
    { 
     if (fromMailAddress == null) 
      throw new Exception(); 
     if (to == null) 
      throw new ArgumentException("No valid recipients were supplied.", "to"); 

     // Mail initialization 
     var mailMsg = new MailMessage 
     { 
      From = fromMailAddress, 
      Subject = subject, 
      Body = body, 
      IsBodyHtml = true, 
      Priority = (highPriority) ? MailPriority.High : MailPriority.Normal 
     }; 

     mailMsg.To.Add(to); 


     smtp.Send(mailMsg); 
    } 
} 

उत्तर

1

मेरा अनुमान है कि SmtpClient से अधिक संदेशों समवर्ती भेजने के लिए तैयार नहीं किया गया है।

मैं इस बजाय तरह वर्ग बदल जाएगा: वहाँ वास्तव में निर्माता में ग्राहक बनाने के लिए कोई कारण नहीं हैं

public class EmailSender : IEmailSender 
{ 
    Queue<MailMessage> _messages = new Queue<MailMessage>(); 
    SmtpClient _client = new SmtpClient(); 

    public EmailSender() 
    { 
    } 

    public void SendMail(MailAddress fromMailAddress, string to, string subject, string body, bool highPriority) 
    { 
     if (fromMailAddress == null) 
      throw new ArgumentNullException("fromMailAddress"); 
     if (to == null) 
      throw new ArgumentException("No valid recipients were supplied.", "to"); 

     // Mail initialization 
     var mailMsg = new MailMessage 
     { 
      From = fromMailAddress, 
      Subject = subject, 
      Body = body, 
      IsBodyHtml = true, 
      Priority = (highPriority) ? MailPriority.High : MailPriority.Normal 
     }; 

     mailMsg.To.Add(to); 

     lock (_messages) 
     { 
      _messages.Enqueue(mailMsg); 
      if (_messages.Count == 1) 
      { 
       ThreadPool.QueueUserWorkItem(SendEmailInternal); 
      } 
     } 
    } 

    protected virtual void SendEmailInternal(object state) 
    { 
     while (true) 
     { 
      MailMessage msg; 
      lock (_messages) 
      { 
       if (_messages.Count == 0) 
        return; 
       msg = _messages.Dequeue(); 
      } 

      _client.Send(msg) 
     } 
    } 
} 

के रूप में।

मैंने यह भी बदल दिया कि कक्षा ArgumentNullException फेंकता है और ExceptionfromMailAddress शून्य है। एक खाली Exception ज्यादा नहीं कहना है ..

अद्यतन

कोड भेजना अभी (और SmtpClient पुन: उपयोग) के लिए एक थ्रेड पूल धागा प्रयोग करते हैं।

+0

या बल्कि एक नया SmtpClient उदाहरण बनाने की तुलना में, ओपी सिर्फ इतना है कि वस्तु लॉक कर सकता संदेश भेजा जाता है जब तक। – Marco

+0

हां कन्स्ट्रो में क्लाइंट बनाने का एक अच्छा कारण है: जब आप एक ही सर्वर कनेक्शन पर एकाधिक ईमेल भेज रहे हैं तो पूल किया जाएगा। Http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.dispose.aspx –

+0

@EnnodeWeerd पर टिप्पणी अनुभाग देखें: अद्यतन कोड देखें। – jgauffin

5

आप Dispose, using या अपने वर्ग EmailSender के लिए डिस्पोजेबल पैटर्न को लागू करने से का उपयोग कर SmtpClient के निपटान के लिए की जरूरत है (जो और अधिक यहाँ क्योंकि आप निर्माता में EmailSender के जीवनकाल के लिए SmtpClient के जीवनकाल प्रयास कर रहे हैं उचित।)

कि इस अपवाद का समाधान हो सकता है।

+0

मैं मानता हूँ हम निपटान करना चाहिए, लेकिन यह वास्तव में इस समस्या का कारण हो सकता है? –

+0

यह हो सकता है। "हर अब और फिर" से अपने प्रश्न समय समाप्ति से संबंधित हो सकता है, सफाई, ... जोड़े सही संसाधन प्रबंधन और देखो अगर अपवाद अभी भी दिखाई देता है। यदि आप इसे पुन: उत्पन्न नहीं कर सकते हैं तो समस्या को इंगित करना मुश्किल है। –

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