標籤:name 方法 target back send image ros using cte
項目背景:
最近在對幾年前的一個項目進行重構,發現發送郵件功能需要一定的時間來處理,而由於發送是同步的因此導致在發送郵件時無法執行後續的操作
實際上發送郵件後只需要將發送結果寫入系統日誌即可對其他業務沒有任何影響,因此決定將發送郵件操作更改為非同步 由於使用的是C#的郵件類庫,而C#本身已經提供了非同步發送的功能即只需要將Send方法更改為SendAsync即可,更改方法名並不難但發送後再寫入日誌就有點難了因為項目中發送郵件是單獨的組件,所以我不可能在發送郵件類庫中直接添加寫入日誌操作(不在同一個類庫,網路和MSDN上的例子都是同一組件下)但C#可以使用委託將方法作為參數來傳遞的,因此我就可以在發送郵件的方法中添加一個回調方法,在非同步發送郵件後再執行回調方法即可 完整代碼:
/****************************************************************** * 建立人:HTL * 建立時間:2015-04-16 21:34:25 * 說明:C# 發送非同步郵件Demo * Email:[email protected] *******************************************************************/using System;using System.Net.Mail;namespace SendAsyncEmailTest{ class Program { const string dateFormat = "yyyy-MM-dd :HH:mm:ss:ffffff"; static void Main(string[] args) { Console.WriteLine("開始非同步發送郵件,時間:" + DateTime.Now.ToString(dateFormat)); new MailHelper().SendAsync("Send Async Email Test", "This is Send Async Email Test", "[email protected]", emailCompleted); Console.WriteLine("郵件正在非同步發送,時間:" + DateTime.Now.ToString(dateFormat)); Console.ReadKey(); Console.WriteLine(); } /// <summary> /// 郵件發送後的回調方法 /// </summary> /// <param name="message"></param> static void emailCompleted(string message) { //延時1秒 System.Threading.Thread.Sleep(1000); Console.WriteLine(); Console.WriteLine("郵件發送結果:\r\n" + (message == "true" ? "郵件發送成功" : "郵件發送失敗") + ",時間:" + DateTime.Now.ToString(dateFormat)); //寫入日誌 } } /// <summary> /// 發送郵件類 /// </summary> public class MailHelper { public delegate int MethodDelegate(int x, int y); private readonly int smtpPort = 25; readonly string SmtpServer = "smtp.baidu.com"; private readonly string UserName = "[email protected]"; readonly string Pwd = "baidu.com"; private readonly string AuthorName = "BaiDu"; public string Subject { get; set; } public string Body { get; set; } public string Tos { get; set; } public bool EnableSsl { get; set; } MailMessage GetClient { get { if (string.IsNullOrEmpty(Tos)) return null; MailMessage mailMessage = new MailMessage(); //多個接收者 foreach (string _str in Tos.Split(‘,‘)) { mailMessage.To.Add(_str); } mailMessage.From = new System.Net.Mail.MailAddress(UserName, AuthorName); mailMessage.Subject = Subject; mailMessage.Body = Body; mailMessage.IsBodyHtml = true; mailMessage.BodyEncoding = System.Text.Encoding.UTF8; mailMessage.SubjectEncoding = System.Text.Encoding.UTF8; mailMessage.Priority = System.Net.Mail.MailPriority.High; return mailMessage; } } SmtpClient GetSmtpClient { get { return new SmtpClient { UseDefaultCredentials = false, Credentials = new System.Net.NetworkCredential(UserName, Pwd), DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network, Host = SmtpServer, Port = smtpPort, EnableSsl = EnableSsl, }; } } //回調方法 Action<string> actionSendCompletedCallback = null; ///// <summary> ///// 使用非同步發送郵件 ///// </summary> ///// <param name="subject">主題</param> ///// <param name="body">內容</param> ///// <param name="to">接收者,以,分隔多個接收者</param> //// <param name="_actinCompletedCallback">郵件發送後的回調方法</param> ///// <returns></returns> public void SendAsync(string subject, string body, string to, Action<string> _actinCompletedCallback) { if (string.IsNullOrEmpty(to)) return; Tos = to; SmtpClient smtpClient = GetSmtpClient; MailMessage mailMessage = GetClient; if (smtpClient == null || mailMessage == null) return; Subject = subject; Body = body; EnableSsl = false; //發送郵件回調方法 actionSendCompletedCallback = _actinCompletedCallback; smtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); try { smtpClient.SendAsync(mailMessage, "true");//非同步發送郵件,如果回調方法中參數不為"true"則表示發送失敗 } catch (Exception e) { throw new Exception(e.Message); } finally { smtpClient = null; mailMessage = null; } } /// <summary> /// 非同步作業完成後執行回調方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void SendCompletedCallback(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { //同一組件下不需要回調方法,直接在此寫入日誌即可 //寫入日誌 //return; if (actionSendCompletedCallback == null) return; string message = string.Empty; if (e.Cancelled) { message = "非同步作業取消"; } else if (e.Error != null) { message = (string.Format("UserState:{0},Message:{1}", (string)e.UserState, e.Error.ToString())); } else message = (string)e.UserState; //執行回調方法 actionSendCompletedCallback(message); } }}
有圖有真相 參考:
Cnblogs.com C#委託的介紹(delegate、Action、Func、predicate)MSDN Action 委託MSDN SimpleAsynchronousExample【已解決】C#中如何把函數當做參數傳遞到別的函數中
codeproject.com Send asynchronous mail using asp.net
C# 使用系統方法發送非同步郵件