ورود

View Full Version : سوال: با تاخیر فرستادن ایمیل



ندااحمدی
سه شنبه 08 آذر 1390, 10:30 صبح
چصور میتوانم ایمیل های خود را با تاخیر مثلا پنج دقیقه بفرستم این کد فرستادن ایمیلم است
لطفا در کدهایش راهنمایی کنید
public void SendEmail(string Email ,string mBody ,string mSubject ,string message)
{
try{
hatra.lang ln = new hatra.lang(ref oMess);
string strBody = mBody;
string strSiteAddress = (new hatra.settings(ln.LangId.ToString(), ref oMess)).Settings_SiteAddress;
strBody = strBody.Replace("[Email]", Email);
strBody = strBody.Replace("[SiteAddress]", strSiteAddress);
System.Net.Mail.MailMessage objMailMsg = new System.Net.Mail.MailMessage();
System.Net.Mail.MailAddress addressFrom = new System.Net.Mail.MailAddress("info@" + strSiteAddress);
System.Net.Mail.MailAddress addressTo = new System.Net.Mail.MailAddress(Email);
objMailMsg.From = addressFrom;
objMailMsg.To.Add(addressTo);
objMailMsg.Subject = mSubject;
objMailMsg.Body = strBody;
objMailMsg.BodyEncoding = System.Text.Encoding.UTF8;
objMailMsg.IsBodyHtml = true;
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient();
smtp.Host = "mail." + strSiteAddress;
System.Threading.Thread.Sleep(5000);
smtp.Send(objMailMsg);
message = "ايميل با موفقيت ارسال شد";
oMess.addMessage(
hatra.MessageTypes.Message,
"SNSEEMM0169",
"ايميل با موفقيت ارسال شد",
"SendToNewsLetterMember",
hatra.MessageStatus.Successful
);

}catch(Exception ex){
oMess.addMessage(
hatra.MessageTypes.Error,
"SNSEEME0170",
"خطا در پايگاه داده: "+ex.Message.ToString(),
ex.Source,
hatra.MessageStatus.Fail
);

}

}

meisam3322
سه شنبه 08 آذر 1390, 17:01 عصر
با سلام،

دوست عزیز فکر کنم مشکل تاخیر شما برای کد زیر باشه :


System.Threading.Thread.Sleep(5000)

تابع Sleep مقداری رو بر اساس میلی ثانیه دریافت ، و بر اساس اون یک وقفه در ادامه انجام عملیات و کدها ایجاد میکنه

اون کد رو حذف کنین ببینین تغییری ایجاد میشه یا نه ؟ اگه حل نشد اعلام کنین

با آرزوی موفقیت

Javad_Darvish_Amiry
چهارشنبه 09 آذر 1390, 01:04 صبح
سلام. شما قبلا هم این سوال رو پرسیدید؛ اما ظاهرا راهنمایی دوستان راهگشا نبوده براتون. من یه کد ساده با استفاده از Thread براتون میذارم؛ اگه جایی مشکل دارید، لطفا بپرسید؛ اگر هم کارتون پیچیده تر از اینه که با این کد راه بیفته، با توجه به این که تو پست قبلیتون مباحث خوبی مطرح شد، پیشنهاد میکنم موضوع رو از همون پست پیگیری کنید؛ فکر کنم نتیجه بهتری میگیرید؛
اول مشکل کد بالا اینه که شما Sleep رو در رشته جاری فراخوانی میکنید (رشته ای که داره متود بالا رو اجرا میکنه) و برای همین به منظورتون نمیرسید؛ یعنی اجرای متود بالا وقتی به Sleep میرسه، 5 ثانیه متوقف میشه و بعد به کارش ادامه میده. اما از پست قبلیتون اینطور برمیومد که شما میخواید رشته جاری به فعالیتش ادامه بده (و مثلا صفحه aspxتون رو پردازش کنه و به کلاینت بفرسته -بدون توقف) و در عین حال ایمیلتون بعد 5 ثانیه ارسال شه. اگه اینطور هست، ادامه:

اول یه نوع جدید تعریف کنید که پارامتر ها رو در اون بریزید تا مدیریت براتون راحت شه. مثلا اسم این نوع رو میذاریم MailVariables. به این شکل:


public class MailVariables {
public string Email { get; set; }
public string Body { get; set; }
public string Subject { get; set; }
public string Message { get; set; }
}


بعد یه متود استاتیک تعریف کنید که بجای دریافت آرگومانها بصورت تکی (مثل متود اصلی که بالا تعریف کردید) یه آرگومان از نوع تعریف شده (کلاس) جدید بگیره. این متود رو میتونید هرجایی تعریف کنید؛ فرض رو بر این میذاریم که شما اونو تو کد-بیهایند صفحه aspxتون تعریف کردید:


static private void SendEmail(MailVariables mailVariables) {
// حالا متود اصلی ارسال ایمیل را در بلاک قرار دهید؛
// متغیر mailVariables شامل مشخصاتی است که شما برای استفاده در متود به آن نیاز دارید.
// یعنی کد زیر را:
/*
try {
hatra.lang ln = new hatra.lang(ref oMess);
string strBody = mBody;
*/
// همینطور تا آخر.....
// لطفا دقت کنید که در اینجا دیگه دسترسی به مثلا
// mBody
// ندارید و باید اونو از توی
// mailVariables
// بخونید. یعنی به این شکل:
// mailVariables.Body
}


متود اصلی ارسال ایمیلتون رو داخل این بلاک منتقل کنید؛ یعنی حالا ارسال ایمیل باید از تو این متود انجام بشه؛

حالا متود اصلیتون رو (همون متود SendEmail که در سوال مطرح کردید) به شکل زیر تغییر بدید:


public void SendEmail(string Email, string mBody, string mSubject, string message) {
try {

// ایجاد یک نخ جدید؛ و پاس دادن متد ارسال ایمیل به آن
var thread = new System.Threading.Thread((obj) => {

// ایجاد وقفه ی 5 ثانیه در نخ جدید؛ نخ اصلی به روند عادی خود ادامه می دهد و دچار وقفه نمی شود
System.Threading.Thread.Sleep(5000);

// چهار پارامتر را که در شیئ از نوع
// MailVariables
// ریخته ایم، در قالب یک object به متود ارسال خواهد شد که باید آنرا به نوع مورد نظر کاست کنیم
var mailVariables = obj as MailVariables;

// اگر کاست موفقیت آمیز بود، متود استاتیک ارسال ایمیل را با متغیری که حاوی مقادیر مورد نظرمان است فراخوانی میکنیم
if(!Object.ReferenceEquals(mailVariables, null)) {
SendEmail(mailVariables);
}

// متوقف کردن نخ
System.Threading.Thread.CurrentThread.Abort();
});

// آرگومانهای تابع را برای مدیریت بهتر در متغیری از نوع جدیدی که ایجاد کردیم میریزیم
var mail = new MailVariables {
Email = Email,
Body = mBody,
Subject = mSubject,
Message = message
};

// نخ تعریف شده در مراحل بالا را با پاس دادن متغیر فوق شروع میکنیم
thread.Start(mail);
} catch(Exception ex) {
// خطا را مدیریت کنید.....
}

}


این کد به ازای هر بار فراخوانی SendEmail یه رشته (نخ - Thread) جدید ایجاد میکنه؛ در ترید جدید 5 ثانیه توقف میکنه؛ بعد متود اصلی ارسال ایمیل رو فراخوانی کرده و بعد هم به عمر ترید پایان میده؛ دقت کنید که آرگومانهای ارسال ایمیل رو در شیئ از نوع MailVariables ریختیم و با اون داریم کار میکنیم؛
نکته مهم، توجه به بحث های پست قبلیتون هست. مثلا اگه تعداد ایمیلهایی که میخواد ارسال کنید زیاد باشه، اول اینکه در اثر زیاد شدن ترید ها، احتمالا سرور دسترسی شما رو محدود میکنه، و ثانیا استفاده از Thread در اینجور مواقع توصیه نمیشه و راهکارهای بهتری هست، از جمله ThreadPool و Timer و cashe-callback که قبلا بحث شد.

ضمنا این خط رو
System.Threading.Thread.Sleep(5000);
از تو کد خودتون حذف کنید؛ من اون رو در جای مناسبش قرار دادم.

اگه سوالی بود در خدمتم. موفق باشید.