मेल क्लाइंट्स में मल्टीथ्रेडिंग समर्थन और कनेक्शन पूल

मेल क्लाइंट्स जैसे ImapClient, Pop3Client, and SmtpClient मल्टीथ्रेडेड पर्यावरण में उपयोग किया जा सकता है। क्लाइंट सर्वर के साथ एक या अधिक कनेक्शन रख सकता है। क्लाइंट के भीतर कनेक्शन सेट को प्रबंधित करने के लिए कनेक्शन पूल का उपयोग किया जाता है। एक ही समय में निर्मित और उपयोग किए जा सकने वाले कनेक्शन की संख्या CredentialsByHostClient.MaxConnectionsPerServer प्रॉपर्टी। इस प्रॉपर्टी को 1 या उससे अधिक मान पर सेट किया जा सकता है। डिफ़ॉल्ट रूप से, यह 10 के बराबर है।

प्रत्येक कनेक्शन के लिए कमांड कतार लागू की गई है ताकि मल्टीथ्रेडिंग ऑपरेशन्स को समर्थन मिल सके। कमांड प्रोटोकॉल में परिभाषित सबसे सरल ऑपरेशन्स को लागू करते हैं, जैसे Noop, Authenticate, आदि। उपयोगकर्ता उपलब्ध कनेक्शन से अधिक कमांड शुरू कर सकता है, लेकिन वे तभी चलेंगे जब क्लाइंट ऑपरेशन के लिए नया कनेक्शन बना सके।

मल्टीथ्रेडेड पर्यावरण में मेल क्लाइंट्स का व्यवहार

ईमेल क्लाइंट्स का निम्नलिखित व्यवहार होता है:

  1. जब MaxConnectionsPerServer = 1, क्लाइंट एक कनेक्शन बनाता है और प्रमाणीकरण व प्राधिकरण करता है। यह कनेक्शन क्लाइंट के निष्कासित होने तक काम करते हुए रहता है। विभिन्न थ्रेड्स से सभी ऑपरेशन्स मुख्य कनेक्शन में रखा गया कमांड कतार में निर्देशित होते हैं।

  2. जब MaxConnectionsPerServer > 1, क्लाइंट आवश्यक संख्या में कनेक्शन बनाता है और प्रत्येक कनेक्शन के लिए प्रमाणीकरण और प्राधिकरण करता है। एक कनेक्शन मुख्य कनेक्शन के रूप में आरक्षित रहता है। यह कनेक्शन क्लाइंट के निष्कासित होने तक काम करते हुए रहता है। अन्य सभी कनेक्शन मांग पर बनाए और निष्कासित किए जाते हैं। ऐसी कनेक्शन की अधिकतम संख्या है MaxConnectionsPerServer प्रॉपर्टी। उदाहरण के लिए, यदि MaxConnectionsPerServer = 2, फिर एक कनेक्शन मुख्य कनेक्शन के रूप में आरक्षित होता है, और दूसरा कनेक्शन अतिरिक्त के रूप में अन्य थ्रेड्स में चलाए गए ऑपरेशनों के लिए उपयोग होता है। इसलिए, यदि MaxConnectionsPerServer = 3, फिर पहला कनेक्शन मुख्य कनेक्शन के रूप में आरक्षित होता है, और दो अन्य कनेक्शन अतिरिक्त के रूप में अन्य थ्रेड्स में चलाए गए ऑपरेशनों के लिए उपयोग होते हैं। जब किसी नए थ्रेड से कनेक्शन का अनुरोध आता है और सभी कनेक्शन पहले से ही उपयोग में होते हैं, तो क्लाइंट तब तक इंतज़ार करता है जब तक उपयोग किए गए कनेक्शन की संख्या घट नहीं जाती। यह बहुत महत्वपूर्ण बिंदु है जो यह स्पष्ट करता है कि कनेक्शन को सही ढंग से निष्कासित करना क्यों आवश्यक है।

मल्टीथ्रेडेड पर्यावरण में मेल क्लाइंट्स के उपयोग के उदाहरण

एक उपयोगकर्ता विभिन्न थ्रेड्स में ऑपरेशन्स को कई तरीकों से चला सकता है। इन्हें दो प्रकार में विभाजित किया जा सकता है।

असिंक्रोनस (Begin/End) विधियों का उपयोग

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

// Create an imapclient with host, user and password
ImapClient client = new ImapClient();
client.Host = "domain.com";
client.Username = "username";
client.Password = "password";
client.SelectFolder("InBox");

ImapMessageInfoCollection messages = client.ListMessages();
IAsyncResult res1 = client.BeginFetchMessage(messages[0].UniqueId);
IAsyncResult res2 = client.BeginFetchMessage(messages[1].UniqueId);
MailMessage msg1 = client.EndFetchMessage(res1);
MailMessage msg2 = client.EndFetchMessage(res2);

उपयोगकर्ता‑निर्मित थ्रेड्स का उपयोग

एक उपयोगकर्ता निम्नलिखित वस्तुओं का उपयोग करके थ्रेड बना सकता है Thread, ThreadPool, Task, या किसी अन्य वस्तु जो इस उद्देश्य के लिए बनाई गई हो। उपयोगकर्ता थर्ड‑पार्टी कोड में निर्मित थ्रेड्स का भी उपयोग कर सकता है। इस स्थिति में, क्लाइंट के दो व्यवहार मॉडल होते हैं।

क. यदि उपयोगकर्ता ने थ्रेड में अतिरिक्त कनेक्शन बनाने का ध्यान नहीं रखा, तो सभी ऑपरेशनों को मुख्य कनेक्शन की कमांड कतार में भेजा जाएगा। नीचे अतिरिक्त थ्रेड में नई कनेक्शन बिना बनाए सभी लेनदेन मुख्य कनेक्शन के माध्यम से किए गए हैं का उदाहरण है:

List<MailMessage> List = new List<MailMessage>();
ThreadPool.QueueUserWorkItem(delegate(object o)
{
    client.SelectFolder("folderName");
    ImapMessageInfoCollection messageInfoCol = client.ListMessages();
    foreach (ImapMessageInfo messageInfo in messageInfoCol)
    {
        List.Add(client.FetchMessage(messageInfo.UniqueId));
    }
});

ख. जब उपयोगकर्ता अतिरिक्त थ्रेड के लिए नई कनेक्शन बनाने की विधि चलाता है, तो यह थ्रेड तब तक ब्लॉक रहता है जब तक नई कनेक्शन के लिए कोटा मान बदलकर नई कनेक्शन की अनुमति नहीं देता। फिर नई कनेक्शन बनती है। यह कनेक्शन उस थ्रेड में सभी ऑपरेशनों के लिए डिफ़ॉल्ट कनेक्शन बन जाता है। सभी ऑपरेशनों के पूरा होने पर, कनेक्शन को निष्कासित करना होगा। नई कनेक्शन बनाने के लिए, उपयोग करें CredentialsByHostClient.CreateConnection विधि। यह विधि एक ऑब्जेक्ट लौटाती है जो लागू करता है IDisposable इंटरफ़ेस। कनेक्शन को रिलीज़ करने के लिए, Dispose विधि को कॉल करना आवश्यक है। कनेक्शन बनाना और निष्कासित करना थ्रेड के भीतर होना चाहिए जहाँ मेल ऑपरेशन्स चलाए जा रहे हों। उसी थ्रेड में नई कनेक्शन बनाने का प्रयास जहाँ मेल क्लाइंट बनाया गया था, त्रुटि देता है, क्योंकि उस क्षण वह थ्रेड नई कनेक्शन बनाने के लिए उपयोग नहीं किया जा सकता। नई कनेक्शन बनाना संभव नहीं है जब MaxConnectionsPerServer = 1. अतिरिक्त थ्रेड में नई कनेक्शन बनाने का कोड उदाहरण:

List<MailMessage> List1 = new List<MailMessage>();
ThreadPool.QueueUserWorkItem(delegate(object o)
{
    using (IDisposable connection = client.CreateConnection())
    {
        client.SelectFolder("FolderName");
        ImapMessageInfoCollection messageInfoCol = client.ListMessages();
        foreach (ImapMessageInfo messageInfo in messageInfoCol)
            List1.Add(client.FetchMessage(messageInfo.UniqueId));
    }
});

कनेक्शन पूल

Aspose.Email 19.3 से शुरू करके, कनेक्शन पूल को पुनः संरचित किया गया। EmailClient क्लास प्रस्तुत किया गया, जो अंततः CredentialsByHostClient class। यह EmailClient क्लास एक प्रदान करता है ConnectionAsgmtMode प्रॉपर्टी जो मल्टीथ्रेडेड पर्यावरण में कनेक्शन आवंटन मोड को परिभाषित करती है। EmailClient.ConnectionAsgmtMode का उपयोग करके सेट किया जाता है ConnectionAsgmtType enumeration।

कनेक्शन प्रकार

तीन प्रकार के कनेक्शन हैं:

  • मुख्य कनेक्शन। यह वह कनेक्शन है जो मेल क्लाइंट के साथ बनाया और निष्कासित होता है। इसे मैन्युअल रूप से नहीं बनाया या निष्कासित किया जा सकता।
  • डिफ़ॉल्ट कनेक्शन। उपयोगकर्ता थ्रेड्स के लिए डिफ़ॉल्ट कनेक्शन बना सकता है CreateConnection विधि से बनाए जा सकते हैं। यदि डिफ़ॉल्ट कनेक्शन मौजूद है, तो थ्रेड में चलाए गए ईमेल क्लाइंट की सभी विधियाँ निहित रूप से इस कनेक्शन का उपयोग करेंगी। प्रति थ्रेड केवल एक डिफ़ॉल्ट कनेक्शन मौजूद हो सकता है। इसे मैन्युअल या स्वचालित रूप से बनाया जा सकता है, यह EmailClient.ConnectionAsgmtMode प्रॉपर्टी। ये कनेक्शन मैन्युअल रूप से EmailClient.CreateConnection(createAsDefaultConnection = true) विधि से बनाए जा सकते हैं। यदि डिफ़ॉल्ट कनेक्शन उपयोग नहीं किया गया (कनेक्शन अलोकेशन मोड पर निर्भर), तो मुख्य कनेक्शन निहित रूप से इसका उपयोग करता है।
  • स्वतंत्र कनेक्शन। ये वे कनेक्शन हैं जो थ्रेड्स से संबद्ध नहीं होते। इन्हें मैन्युअल रूप से बनाया जा सकता है और विधि पैरामीटर के रूप में स्पष्ट रूप से उपयोग करना पड़ता है। ये कनेक्शन मैन्युअल रूप से EmailClient.CreateConnection() विधि या वह EmailClient.CreateConnection(createAsDefaultConnection = false) विधि।

कनेक्शन आवंटन प्रकार

सेट करने के लिए EmailClient.ConnectionAsgmtMode प्रॉपर्टी, वह ConnectionAsgmtType एन्यूमरेशन का उपयोग किया जाता है। यह प्रदान किए जाने वाले अलोकेशन प्रकार नीचे सूचीबद्ध हैं।

  • ConnectionAsgmtType.UseMainOrDefault यह मोड ईमेल क्लाइंट में डिफ़ॉल्ट रूप से उपयोग होता है। ईमेल क्लाइंट सभी थ्रेड्स से कई ऑपरेशनों के लिए मुख्य कनेक्शन का उपयोग करता है यदि डिफ़ॉल्ट कनेक्शन नहीं बनाया गया हो, या यदि किसी विधि पैरामीटर के रूप में स्पष्ट रूप से कनेक्शन नहीं पास किया गया हो। मुख्य कनेक्शन ईमेल क्लाइंट के निर्माण के साथ ही बनता है। उपयोगकर्ता थ्रेड्स के लिए डिफ़ॉल्ट कनेक्शन बना सकता है CreateConnection विधि। यदि किसी थ्रेड के लिए डिफ़ॉल्ट कनेक्शन बनता है, तो वह उस थ्रेड में कॉल की गई सभी ईमेल क्लाइंट विधियों के लिए निहित रूप से उपयोग होता है। यदि थ्रेड के लिए डिफ़ॉल्ट कनेक्शन नहीं बनता, तो मुख्य कनेक्शन सभी विधियों के लिए उपयोग किया जाता है। उपयोगकर्ता थ्रेड्स से असंबद्ध कनेक्शन भी बना सकता है CreateConnection विधि। अन्य कनेक्शन (न तो मुख्य और न ही डिफ़ॉल्ट) उपयोग करने के लिए, उपयोगकर्ता को कनेक्शन को स्पष्ट रूप से विधि पैरामीटर के रूप में पास करना होगा। उपयोगकर्ता अतिरिक्त रूप से किसी भी संख्या में कनेक्शन बना सकता है। प्रति थ्रेड केवल एक डिफ़ॉल्ट कनेक्शन मौजूद हो सकता है। कृपया ध्यान दें कि डिफ़ॉल्ट कनेक्शन सही ढंग से काम करते हैं यदि उपयोगकर्ता Thread मल्टीटास्किंग प्रोग्रामिंग के लिए वस्तुएँ। यदि उपयोगकर्ता कनेक्शन पूल या Task मल्टीटास्किंग के लिए वस्तुएँ, यह मोड गलत व्यवहार का कारण बन सकता है। इस समस्या से बचने के लिए, उपयोगकर्ता को कोड निष्पादन के अंत में डिफ़ॉल्ट कनेक्शन (यदि उपयोग किया गया हो) को मैन्युअल रूप से निष्कासित करना होगा।

  • ConnectionAsgmtType.UseMain ईमेल क्लाइंट सभी थ्रेड्स से कई ऑपरेशनों के लिए मुख्य कनेक्शन का उपयोग करता है। मुख्य कनेक्शन ईमेल क्लाइंट के निर्माण के साथ ही बनता है। उपयोगकर्ता डिफ़ॉल्ट कनेक्शन नहीं बना सकता, लेकिन थ्रेड्स से असंबद्ध कनेक्शन बना सकता है CreateConnection विधि के साथ नहीं बना सकता। अन्य कनेक्शन उपयोग करने के लिए, उपयोगकर्ता को उन्हें स्पष्ट रूप से विधि पैरामीटर के रूप में पास करना होगा।

  • ConnectionAsgmtType.UseDefault ईमेल क्लाइंट सभी थ्रेड्स से कई ऑपरेशनों के लिए केवल डिफ़ॉल्ट कनेक्शनों का निहित रूप से उपयोग करता है। इस मोड में मुख्य कनेक्शन का उपयोग नहीं किया जाता। यदि किसी थ्रेड के लिए डिफ़ॉल्ट कनेक्शन नहीं बनाया गया है (ईमेल क्लाइंट विधि के पहले कॉल पर), तो ईमेल क्लाइंट पहला ऑपरेशन चलाने से पहले उस थ्रेड के लिए निहित रूप से डिफ़ॉल्ट कनेक्शन बनाता है। उपयोगकर्ता थ्रेड्स के लिए डिफ़ॉल्ट कनेक्शन को CreateConnection विधि का उपयोग करता है क्योंकि वे स्वयं व स्वचालित रूप से बनते हैं। उपयोगकर्ता थ्रेड्स से असंबद्ध कनेक्शन भी बना सकता है CreateConnection विधि का उपयोग करता है। अन्य कनेक्शन उपयोग करने के लिए, उपयोगकर्ता को उन्हें स्पष्ट रूप से विधि पैरामीटर के रूप में पास करना होगा। उपयोगकर्ता अतिरिक्त रूप से किसी भी संख्या में कनेक्शन बना सकता है। प्रति थ्रेड केवल एक डिफ़ॉल्ट कनेक्शन उपयोग किया जा सकता है। कृपया ध्यान दें कि डिफ़ॉल्ट कनेक्शन सही ढंग से काम करते हैं यदि उपयोगकर्ता Thread मल्टीटास्किंग प्रोग्रामिंग के लिए वस्तुएँ। यदि उपयोगकर्ता कनेक्शन पूल या Task मल्टीटास्किंग के लिए वस्तुएँ, यह मोड गलत व्यवहार का कारण बन सकता है। इस समस्या से बचने के लिए, उपयोगकर्ता को कोड निष्पादन के अंत में डिफ़ॉल्ट कनेक्शन को मैन्युअल रूप से निष्कासित करना होगा।

सिफारिशें

यदि उपयोगकर्ता सभी कमांड मुख्य कनेक्शन को भेजता है, तो विभिन्न थ्रेडों से कमांड मिश्रित हो सकते हैं। उपयोगकर्ता को समझना चाहिए कि कौन से कमांड उनके क्रम पर निर्भर करते हैं और ऐसे कमांड को सिंक्रनाइज़ करने के लिए उपाय करना चाहिए। यह भी आवश्यक है कि विभिन्न सत्रों (IMAP/POP3) में कमांड चलाने की संभावना पर विचार किया जाए। सबसे समय-खपत वाले कार्य हैं FetchMessage, AppendMessage, and Send. यह संभवतः समझ में आता है कि इन कार्यों को नई थ्रेड और नई कनेक्शन के साथ किया जाए। तेज़ कार्य जैसे Delete मुख्य कनेक्शन के साथ करने के लिए समझ में आता है। कृपया ध्यान दें कि नई कनेक्शन की प्रारम्भिककरण एक काफी समय लेने वाला कार्य है।