2012-01-07 28 views
8

यहां सरल अवधारणा। यह एमवीसी 3 और एंटिटी फ्रेमवर्क 4 का उपयोग करके बनाई जा रही साइट के लिए है। उपयोगकर्ता द्वारा साइट पर पंजीकरण करने के बाद, उनके ईमेल पते पर एक ईमेल भेजा जाता है। मैंने सबसे पहले SmtpClient.Send() का उपयोग करके इसे कार्यान्वित किया और यह ठीक काम किया। तब मुझे ईमेल को अतुल्यकालिक रूप से भेजने का प्रयास करने का उज्ज्वल विचार मिला। मुझे दो एसिंक दृष्टिकोणों के साथ समस्याएं आ रही हैं जिनकी मैंने कोशिश की है।SmtpClient के माध्यम से असीमित रूप से ईमेल भेजने के दो तरीके, विभिन्न परिणाम

पहले कार्यान्वयन (यह अनुत्तरित पद से: https://stackoverflow.com/questions/7558582/how-to-dispose-using-smtpclient-send-and-asynccallback):

public bool Emailer(){ 
    . 
    . 
    . 
    using (var smtpClient = new SmtpClient()) 
    { 
     smtpClient.EnableSsl = true; 
     smtpClient.Host = "smtp.gmail.com"; 
     smtpClient.Port = 587; 
     smtpClient.UseDefaultCredentials = false; 
     smtpClient.Credentials = new NetworkCredential("[email protected]", "mypassword"); 

     var sd = new SendEmailDelegate(smtpClient.Send); 
     var cb = new AsyncCallback(SendEmailResponse); 
     sd.BeginInvoke(message, cb, sd); 

     return true; 
    } 
} 

private delegate void SendEmailDelegate(System.Net.Mail.MailMessage m); 

private static void SendEmailResponse(IAsyncResult ar) 
{ 
    try 
    { 
     SendEmailDelegate sd = (SendEmailDelegate)(ar.AsyncState); 
     sd.EndInvoke(ar); // "cannot access a disposed object" errors here 
    } 
    catch (Exception e) 
    { 
     _logger.WarnException("Error on EndInvoke.", e); 
    } 
} 

यह आधे समय में काम किया। दूसरी छमाही मुझे कॉलबैक में "एक डिस्पोजेड ऑब्जेक्ट तक नहीं पहुंच सकता" त्रुटि प्राप्त होगी।

अगला कार्यान्वयन (ठोस प्रतिष्ठा के साथ एक सदस्य से: What are best practices for using SmtpClient, SendAsync and Dispose under .NET 4.0):

var smtpClient = new SmtpClient(); 
smtpClient.EnableSsl = true; 
smtpClient.Host = "smtp.gmail.com"; 
smtpClient.Port = 587; 
smtpClient.UseDefaultCredentials = false; 
smtpClient.Credentials = new NetworkCredential("[email protected]", "mypassword"); 

smtpClient.SendCompleted += (s, e) => 
    { 
     smtpClient.Dispose(); 
     message.Dispose(); 
    }; 
smtpClient.SendAsync(message, null); 
इस कार्यान्वयन मैं किसी भी त्रुटि मिल न के साथ

, लेकिन वहाँ एक काफ़ी लंबे समय तक देरी (~ 5 सेकंड) डिबगिंग मोड SmtpClient में जब है। SendAsync() निष्पादित करता है, जिससे मुझे लगता है कि यह अतुल्यकालिक रूप से नहीं भेजा जा रहा है।

सवाल:

1) क्या पहली विधि है कि "निपटाए वस्तु" त्रुटियों के कारण में गलत क्या है?

2) क्या दूसरे कार्यान्वयन में ऐसी समस्या है जो ईमेल को असीमित रूप से नहीं भेज रहा है? 5-सेकंड देरी अर्थहीन है?

यह भी ध्यान रखना महत्वपूर्ण हो सकता है कि हालांकि साइट को बड़ी संख्या में ईमेल भेजने (केवल उपयोगकर्ता पंजीकरण, ऑप्ट-इन न्यूज़लेटर्स इत्यादि) भेजने में सहायता करने की आवश्यकता नहीं होगी, हम भविष्य में बड़ी संख्या में उपयोगकर्ताओं की उम्मीद करते हैं, इसलिए ईमेल को असीमित रूप से भेजने का मेरा निर्णय।

धन्यवाद।

उत्तर

7

आपकी मुट्ठी विधि यूएसआईएन-ब्लॉक की वजह से ठीक से काम नहीं करेगी। उपयोग-ब्लॉक समाप्त होने के बाद, SmtpClient ऑब्जेक्ट का निपटारा किया जाएगा। तो आप अपने ईवेंट हैंडलर में इसका उपयोग नहीं कर सकते हैं।

+0

उत्तर के लिए धन्यवाद। अब मैं देखता हूं कि हैंडलर को आग लगाने का मौका देने से पहले ऑब्जेक्ट का निपटारा किया जाता है। साथ ही, मैं समझता हूं कि दोनों SmtpClient का निपटान किया जाना चाहिए और EndInvoke को कॉल किया जाना चाहिए। क्या दृष्टिकोण # 2 इसे पूरा करता है? –

5

टिप्स: 1-न उपयोग MailMessage objet के लिए "ब्लॉक का उपयोग", यह आपके वस्तु निपटान से पहले मेल भेजा
2-निपटान के SmtpClient.SendCompleted घटना पर MailMessage वस्तुओं:

smtpClient.SendCompleted += (s, e) => 
    { 
     message.Dispose(); 
    }; 

3-सेट SmtpClient वस्तु के लिए SendCompletedEventHandler

smtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); 

4-अधिक कोड:

private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) 
    { 
     // Get the unique identifier for this asynchronous operation. 
     String token = (string)e.UserState; 

     if (e.Cancelled) 
     { 
      //write your code here 
     } 
     if (e.Error != null) 
     { 
      //write your code here 
     } 
     else //mail sent 
     { 
      //write your code here 
     } 

     mailSent = true; 
    } 
1

SmtpClient.SendAsync एसिंक ईमेल भेजने का पसंदीदा तरीका है क्योंकि यह इस उद्देश्य के लिए विशेष रूप से डिजाइन किए गए SmtpClient विधियों का उपयोग करता है। इसे कार्यान्वित करना भी आसान है और हजारों बार काम करने के लिए साबित हुआ है।

आपकी 5 सेकंड देरी अजीब है और सुझाव है कि ऐसी समस्या है जिसे संबोधित करने की आवश्यकता है। कोड का पहला टुकड़ा सिर्फ समस्या को ढंक रहा है लेकिन इसे खत्म नहीं करता है।

SmtpClient.SendAsync वास्तव में केवल एसिंक्रोनस रूप से भेजेगा कि अपनी वितरण पद्धति नहींSpecifiedPickupDirectory या PickupDirectoryFromIis है। उन मामलों में यह लौटने से पहले पिकअप फ़ोल्डर में संदेश फ़ाइल लिख देगा। अपनी कॉन्फ़िगरेशन फ़ाइल की <smtp> अनुभाग देखें। मेरा अनुमान है कि आप इन तरीकों में से एक का उपयोग कर रहे हैं और समस्या पिकअप फ़ोल्डर के साथ है। पुरानी फाइलें हटाएं जो आपके पास हो सकती हैं और जांचें कि समस्या आपके एंटीवायरस सॉफ़्टवेयर नहीं है, जो संभवतः वायरस के लिए प्रत्येक नई फ़ाइल को खोजती है। जांचें कि क्या एन्क्रिप्शन या संपीड़न गुण सेट हैं। कुछ और भी हो सकता है। यह जांचने का सबसे अच्छा तरीका है कि फ़ोल्डर समस्या का स्रोत है या नहीं, मैन्युअल रूप से इसमें एक ईमेल फ़ाइल का मुकाबला करना है।