.NET 4.0 এর অধীনে SmtpClient, SendAsync এবং নিষ্পত্তি করার জন্য সর্বোত্তম অনুশীলনগুলি কী


116

আমি কীভাবে এখন SmtpClient পরিচালনা করব তা নিয়ে কিছুটা বিড়বিড় হয়ে পড়েছি, বিশেষত যদি আমি সেন্ডএএনসিঙ্ক ব্যবহার করে কল করি। সম্ভবত সেন্ডএএনসিঙ্ক সম্পূর্ণ না হওয়া পর্যন্ত আমার ডিসপোজ কল করা উচিত নয়। তবে আমি কি কখনই এটি কল করতে পারি (উদাঃ, "ব্যবহার করে" ব্যবহার করে)। দৃশ্যপটটি একটি ডাব্লুসিএফ পরিষেবা যা কল করার সময় সময়ে সময়ে ইমেল মেইল ​​করে। বেশিরভাগ গণনাটি দ্রুত, তবে ইমেল প্রেরণে এক বা দ্বিতীয় সময় লাগতে পারে, সুতরাং অ্যাসিঙ্কই পছন্দনীয়।

আমি যখনই মেল পাঠাচ্ছি তখন কি আমার একটি নতুন SmtpClient তৈরি করা উচিত? আমার কি পুরো ডাব্লুসিএফের জন্য একটি তৈরি করা উচিত? সাহায্য করুন!

আপডেট এতে কোনও পার্থক্য আসে, প্রতিটি ইমেল সর্বদা ব্যবহারকারীর কাছে কাস্টমাইজ করা থাকে। ডাব্লুসিএফ অ্যাজুরে হোস্ট করা হয় এবং Gmail এর মেলার হিসাবে ব্যবহৃত হয়।


1
: কিভাবে IDisposable এবং ASYNC হ্যান্ডেল করতে উপর বড় ছবি সম্পর্কে এই পোস্ট দেখতে stackoverflow.com/questions/974945/...
ক্রিস হাস

উত্তর:


139

দ্রষ্টব্য: .NET 4.5 SmtpClient প্রয়োগ async awaitableপদ্ধতি SendMailAsync। নিম্ন সংস্করণগুলির জন্য, SendAsyncনীচে বর্ণিত হিসাবে ব্যবহার করুন ।


আপনার সর্বদা IDisposableপ্রাথমিক সম্ভাবনাতে উদাহরণস্বরূপ নিষ্পত্তি করা উচিত । অ্যাসিঙ্ক কলগুলির ক্ষেত্রে, বার্তা প্রেরণের পরে এটি কলব্যাকে রয়েছে।

var message = new MailMessage("from", "to", "subject", "body"))
var client = new SmtpClient("host");
client.SendCompleted += (s, e) => {
                           client.Dispose();
                           message.Dispose();
                        };
client.SendAsync(message, null);

এটি কিছুটা বিরক্তিকর SendAsyncএকটি কলব্যাক গ্রহণ করে না।


শেষ লাইনে 'অপেক্ষা' করা উচিত নয়?
নিকো

19
এই কোডটি আগে awaitপাওয়া যায় নি উপলব্ধ ছিল। এটি ইভেন্ট হ্যান্ডলারগুলি ব্যবহার করে একটি traditionalতিহ্যবাহী কলব্যাক। awaitনতুন ব্যবহার করা হলে ব্যবহার করা উচিত SendMailAsync
TheCodeKing

3
শ্রীমতি এক্সেপশন: মেল প্রেরণে ব্যর্থ ----> সিস্টেম.আইনডিয়োপ্পেরেশন এক্সসেপশন: এই মুহুর্তে একটি অ্যাসিঙ্ক্রোনাস অপারেশন শুরু করা যায় না। অ্যাসিঙ্ক্রোনাস অপারেশনগুলি কেবলমাত্র একটি অ্যাসিনক্রোনাস হ্যান্ডলার বা মডিউল বা পেজ লাইফাইসাইকেলের নির্দিষ্ট ইভেন্টগুলির মধ্যে শুরু করা যেতে পারে। যদি কোনও পৃষ্ঠা কার্যকর করার সময় এই ব্যতিক্রম ঘটে থাকে তবে নিশ্চিত হয়ে নিন যে পৃষ্ঠাটি <% @ পৃষ্ঠা Async = "সত্য"%> চিহ্নিত হয়েছে। এই ব্যতিক্রমটি "async বাতিল" পদ্ধতি কল করার প্রয়াসকেও নির্দেশ করতে পারে যা সাধারণত এএসপি.নেট অনুরোধ প্রক্রিয়াজাতকরণের মধ্যে অসমর্থিত। পরিবর্তে, অ্যাসিনক্রোনাস পদ্ধতিতে কোনও কার্য ফিরিয়ে দেওয়া উচিত, এবং কলারটিকে এটির জন্য অপেক্ষা করা উচিত।
মিচিফ

1
nullদ্বিতীয় প্যারামিটার হিসাবে সরবরাহ করা কি নিরাপদ SendAsync(...)?
জোকুল

167

আসল প্রশ্নটি। নেট 4 এর জন্য জিজ্ঞাসা করা হয়েছিল, তবে এটি নেট নেট হিসাবে 4mmpplient async অপেক্ষমান পদ্ধতি প্রয়োগ করে SendMailAsync

ফলস্বরূপ, অবিচ্ছিন্নভাবে ইমেল পাঠানো নিম্নলিখিত হিসাবে রয়েছে:

public async Task SendEmail(string toEmailAddress, string emailSubject, string emailMessage)
{
    using (var message = new MailMessage())
    {
        message.To.Add(toEmailAddress);

        message.Subject = emailSubject;
        message.Body = emailMessage;

        using (var smtpClient = new SmtpClient())
        {
            await smtpClient.SendMailAsync(message);
        }
    }
}

সেন্ডএএনসিঙ্ক পদ্ধতি ব্যবহার না করা ভাল।


কেন এড়ানো ভাল? আমি মনে করি এটি প্রয়োজনীয়তার উপর নির্ভর করে।
জোয়েন

14
সেন্ডমেলঅ্যাসেন্স () সেন্ডএলসিঙ্ক () পদ্ধতির চারপাশে একটি মোড়ক। async / প্রতীক্ষা হ'ল উপায় নিকৃষ্ট এবং আরও মার্জিত। এটি ঠিক একই প্রয়োজনীয়তা অর্জন করবে।
বরিস লিপস্চিটজ

2
@ রড হার্টজেল আপনি সর্বদা ব্যবহার করতে পারেন ont কন্টিনিউউথ ()
বোরিস

2
ব্যবহার করা ভাল - বা নিষ্পত্তি - বা ব্যবহারিক পার্থক্য নেই? এই শেষ 'ব্যবহার' ব্লকটিতে কী সম্ভব নয় যে প্রেরণমাইলঅ্যাকশন কার্যকর করার আগেই smtpClient নিষ্পত্তি করা যেতে পারে?
নিকো

6
MailMessageনিষ্পত্তি করা উচিত।
TheCodeKing

16

সাধারণভাবে, আইডিস্পোজযোগ্য অবজেক্টগুলি যত তাড়াতাড়ি সম্ভব নিষ্পত্তি করা উচিত; কোনও বস্তুর আইডিস্পোজেবল বাস্তবায়ন হ'ল এই সত্যটি জানানোর জন্য যে প্রশ্নে শ্রেণীর ব্যয়বহুল সংস্থান রয়েছে যা নির্বিচারে প্রকাশ করা উচিত। যাইহোক, যদি এই সংস্থানগুলি তৈরি করা ব্যয়বহুল হয় এবং আপনার প্রচুর পরিমাণে এই অবজেক্টগুলি তৈরি করা প্রয়োজন, তবে একটি উদাহরণ মেমোরিতে রাখা এবং এটি পুনরায় ব্যবহার করা ভাল (পারফরম্যান্স ওয়াইস) হতে পারে। এটির কোনও পার্থক্য রয়েছে কিনা তা জানার একমাত্র উপায় রয়েছে: এটি প্রোফাইল করুন!

পুনঃ নিষ্পত্তি এবং অ্যাসিঙ্ক: আপনি usingস্পষ্টত ব্যবহার করতে পারবেন না । পরিবর্তে আপনি সাধারণত কমপ্লেটেড ইভেন্টে অবজেক্টটি নিষ্পত্তি করুন:

var smtpClient = new SmtpClient();
smtpClient.SendCompleted += (s, e) => smtpClient.Dispose();
smtpClient.SendAsync(...);

6

ঠিক আছে, আমি জানি পুরানো প্রশ্ন। আমি যখন এ জাতীয় কিছু বাস্তবায়নের প্রয়োজন হলাম তখন আমি নিজেই এই হোঁচট খেয়েছি। আমি কিছু কোড শেয়ার করতে চেয়েছিলাম।

অবিচ্ছিন্নভাবে বেশ কয়েকটি মেল প্রেরণের জন্য আমি বেশ কয়েকটি শ্রীমতিপি ক্লায়েন্টের মাধ্যমে পুনরাবৃত্তি করছি। আমার সমাধান থিকোডকিংয়ের মতো, তবে আমি পরিবর্তে কলব্যাক অবজেক্টটি নিষ্পত্তি করছি। এটিকে সেন্ড কমপ্লিট ইভেন্টে পাওয়ার জন্য আমি মেইলমেসেজটিও ব্যবহারকারী টোকেন হিসাবে পাস করছি যাতে আমি এটিতেও ডিসপোজ কল করতে পারি। এটার মত:

foreach (Customer customer in Customers)
{
    SmtpClient smtpClient = new SmtpClient(); //SmtpClient configuration out of this scope
    MailMessage message = new MailMessage(); //MailMessage configuration out of this scope

    smtpClient.SendCompleted += (s, e) =>
    {
        SmtpClient callbackClient = s as SmtpClient;
        MailMessage callbackMailMessage = e.UserState as MailMessage;
        callbackClient.Dispose();
        callbackMailMessage.Dispose();
    };

    smtpClient.SendAsync(message, message);
}

2
প্রতিটি ইমেল প্রেরণের জন্য একটি নতুন শ্রীমতিপ্লিয়েন্ট তৈরি করা কি সেরা অনুশীলন?
মার্টন কল


1
ধন্যবাদ! এবং কেবল একটি সংক্ষিপ্ত ব্যাখ্যার জন্য: www.codefrenzy.net/2012/01/30/how-asynchronous-is-smtpclient-sendasync
মার্টন কল

1
এটি একটি সবচেয়ে সহজ এবং নির্ভুল উত্তর যা আমি smtpclient.sendAsync ফাংশন এবং এর সাথে সম্পর্কিত নিষ্পত্তি হ্যান্ডলিংয়ের জন্য স্ট্যাকওভারফ্লোতে পেয়েছি । আমি একটি অ্যাসিনক্রোনাস বাল্ক মেল প্রেরণাগার পাঠিয়েছিলাম। যেহেতু আমি প্রতি কয়েক মিনিটে 50+ বার্তা প্রেরণ করি তাই নিষ্পত্তি পদ্ধতি কার্যকর করা আমার জন্য একটি অত্যন্ত গুরুত্বপূর্ণ পদক্ষেপ ছিল। এই কোডটি আমাকে ঠিক এটি অর্জনে সহায়তা করেছিল। মাল্টি থ্রেডিং পরিবেশের সময় আমি এই কোডটিতে কিছু বাগ খুঁজে পেয়েছিলে আমি উত্তর দেব।
vis2006

1
আমি বলতে পারি যে আপনি যখন লুপে 100+ ইমেল প্রেরণ করেন তখন আপনার পক্ষে এক্সচেঞ্জ সার্ভারটি কনফিগার করার ক্ষমতা না থাকলে (আপনি যদি ব্যবহার করেন) তবে এটি কোনও ভাল পদ্ধতির নয়। সার্ভার মত ব্যতিক্রম নিক্ষেপ করতে পারে 4.3.2 The maximum number of concurrent connections has exceeded a limit, closing trasmission channel। পরিবর্তে কেবল একটি উদাহরণ ব্যবহার করার চেষ্টা করুনSmtpClient
আইবুবি

6

নীচের মন্তব্যে শ্রীমত্পক্লিয়েন্টের নিষ্পত্তি কেন বিশেষভাবে গুরুত্বপূর্ণ তা আপনি দেখতে পারেন:

public class SmtpClient : IDisposable
   // Summary:
    //     Sends a QUIT message to the SMTP server, gracefully ends the TCP connection,
    //     and releases all resources used by the current instance of the System.Net.Mail.SmtpClient
    //     class.
    public void Dispose();

আমার দৃশ্যে ক্লায়েন্টকে নিষ্পত্তি না করে Gmail ব্যবহার করে একাধিক মেইল ​​প্রেরণ করা হয়েছে, আমি পেয়েছিলাম:

বার্তা: পরিষেবা উপলব্ধ নেই, সংক্রমণ চ্যানেল বন্ধ করে দিচ্ছে। সার্ভারের প্রতিক্রিয়াটি ছিল: 4.7.0 অস্থায়ী সিস্টেম সমস্যা। পরে আবার চেষ্টা করুন (ডাব্লুএস)। oo3sm17830090pdb.64 - জিএসএমটিপি


1
আপনার ব্যতিক্রম এখানে ভাগ করে নেওয়ার জন্য ধন্যবাদ যেহেতু আমি এতক্ষণ নিষ্পত্তি না করে এসএমটিপি ক্লায়েন্ট পাঠাচ্ছিলাম। যদিও আমি আমার নিজের এসএমটিপি সার্ভার ব্যবহার করছি তবে একটি ভাল প্রোগ্রামিং অনুশীলন সর্বদা বিবেচনা করা উচিত। আপনার ত্রুটিটি দেখে আমি এখন সাবধানতা পেয়েছি এবং প্ল্যাটফর্মের নির্ভরযোগ্যতা নিশ্চিত করতে ডিসপোজ ফাংশনগুলি অন্তর্ভুক্ত করার জন্য আমার কোডটি সংশোধন করব।
vis2006
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.