实例介绍
【实例简介】
【实例截图】
【核心代码】
using System; using System.Text; using System.Net.Mail; using System.Windows.Forms; using System.Threading.Tasks; using System.Diagnostics; using System.ComponentModel; using System.Collections.Generic; using Mail_Test.Mail; using System.Threading; using System.Collections.Concurrent; using System.IO; namespace Mail_Test { public partial class SendMail : Form { List<string> filePaths = null; List<string> FilePaths { get { if (filePaths == null) filePaths = new List<string>(); return filePaths; } } Stopwatch watch = new Stopwatch(); // 为简便“实验三”跨线程读取数据,所以都先存储在本地变量上 string m_to = String.Empty; string m_cc = String.Empty; string m_bcc = String.Empty; string m_Subject = String.Empty; string m_Body = String.Empty; public SendMail() { InitializeComponent(); // 默认为实验一 this.rdoOne.Checked = true; this.cbbNumber.SelectedIndex = 0; this.cbbNumber.Enabled = false; this.txtTo.Text = Config.TestToAddress; this.txtCC.Text = Config.TestToAddress; this.txtBcc.Text = Config.TestToAddress; } private void btnOk_Click(object sender, EventArgs e) { m_to = this.txtTo.Text.Trim(); m_cc = this.txtCC.Text.Trim(); m_bcc = this.txtBcc.Text.Trim(); m_Subject = this.txtSubject.Text.Trim(); m_Body = this.rtbBody.Text; bool isAsync = this.chbAsync.Checked; bool isReuse = this.cbxReuse.Checked; this.rtbReply.AppendText(String.Format("==============={0},{1}{2}" , (isAsync ? "异步发送" : "同步发送"), (isReuse ? "重用SmtpClient实例" : "新SmtpClient实例"), Environment.NewLine)); watch.Reset(); watch.Start(); // DateTime.Now.ToLongTimeString() if (this.rdoOne.Checked) { #region 实验一:单条邮件同步和异步发送(可通过添加大附件来观察同步异步效果) MailHelper mail = new MailHelper(isAsync); #region 发送单封邮件 中 加入图片链接示例。 // 发送单封邮件 中 加入图片链接示例。 string picPath = Environment.CurrentDirectory "\\附件\\PIC_Mail中文.png"; mail.AddInlineAttachment(picPath, "MyPic"); // 注意内联图片地址写法 cid:ContentId m_Body = m_Body "<br/><img src=\"cid:MyPic\" /><a href=\"cid:MyPic\" target=\"_blank\">点击在新窗口打开图片</a>"; #endregion if (isAsync) { this.SendMessageAsync(mail, true, "实验一", "单条", true, isReuse); } else { this.SendMessage(mail, true, "实验一", "单条", true, isReuse); } #endregion } else if (this.rdoTwo.Checked) { #region 实验二:批量邮件同步和异步发送(单个线程,单个SmtpClient实例,SendAsync()) long count = long.Parse(this.cbbNumber.Text); MailHelper mail = new MailHelper(isAsync); if (isReuse) { if (isAsync) { for (long i = 1; i <= count; i ) { this.SendMessageAsync(mail, false, "实验二", "第" i "条", true, true); } mail.SetBatchMailCount(count); } else { for (long i = 1; i <= count; i ) { this.SendMessage(mail, false, "实验二", "第" i "条", true, true); } mail.SetBatchMailCount(count); } } else { if (isAsync) { for (long i = 1; i <= count; i ) { this.SendMessageAsync(mail, true, "实验二", "第" i "条", true, false); } } else { for (long i = 1; i <= count; i ) { this.SendMessage(mail, true, "实验二", "第" i "条", true, false); } } } #endregion } else if (this.rdoThree.Checked) { #region 实验三:批量邮件同步和异步发送 (平行类库Parallel(自动分区),每个分区一个MailHelper、SmtpClient实例,SendAsync()) long count = long.Parse(this.cbbNumber.Text); if (count != 1) { int fenzu = 0; long sendCount = 0; #region 由系统负荷自动分配最大并发度 // Environment.ProcessorCount; 并行度设置过大会导致资源争用问题,效率不高 // ParallelOptions parallelOptions = new ParallelOptions(); // parallelOptions.MaxDegreeOfParallelism = Environment.ProcessorCount; #endregion ParallelOptions parallelOptions = new ParallelOptions(); // 用一半的线程,因为内部发邮件需要线程池线程 parallelOptions.MaxDegreeOfParallelism = (int)Math.Ceiling((double)Environment.ProcessorCount / 2d); Parallel.For<ParallelInitObj>(1, count 1 , parallelOptions, () => { Interlocked.Increment(ref fenzu); Debug.WriteLine("开始一个分组,当前分组数为:" fenzu.ToString()); ParallelInitObj initObj = new ParallelInitObj() { mail = new MailHelper(isAsync), SumCount = 0, }; return initObj; } , (i, loop, initObj) => { ParallelInitObj curInitObj = initObj; MailHelper mail = curInitObj.mail; Interlocked.Increment(ref sendCount); string shiyan = String.Format("({0})实验三", Thread.CurrentThread.ManagedThreadId); if (isReuse) { if (isAsync) { this.SendMessageAsync(mail, false, shiyan, "第" Thread.VolatileRead(ref sendCount) "条", true, true); curInitObj.SumCount ; } else { this.SendMessage(mail, false, shiyan, "第" Thread.VolatileRead(ref sendCount) "条", true, true); curInitObj.SumCount ; } } else { if (isAsync) { this.SendMessageAsync(mail, true, shiyan, "第" Thread.VolatileRead(ref sendCount) "条", true, false); } else { this.SendMessage(mail, true, shiyan, "第" Thread.VolatileRead(ref sendCount) "条", true, false); } } return curInitObj; } , (initObj) => { ParallelInitObj curInitObj = initObj; if (isReuse) { curInitObj.mail.SetBatchMailCount(curInitObj.SumCount); } Interlocked.Decrement(ref fenzu); Debug.WriteLine("结束一个分组,当前分组数为:" fenzu.ToString()); }); } else { MessageBox.Show("分区发邮件不能为一封"); } #endregion } else if (this.rdoFour.Checked) { #region 实验四:批量邮件同步和异步发送 (平行类库Parallel(手动分区),每个分区一个MailHelper、SmtpClient实例) long count = long.Parse(this.cbbNumber.Text); if (count != 0) { int fenzu = 0; long sendCount = 0; #region 由系统负荷自动分配最大并发度 // OrderablePartitioner<Tuple<long, long>> orderPartition = Partitioner.Create(1, count 1, Environment.ProcessorCount); // ParallelOptions parallelOptions = new ParallelOptions(); // parallelOptions.MaxDegreeOfParallelism = (int)Math.Ceiling((double)Environment.ProcessorCount); #endregion OrderablePartitioner<Tuple<long, long>> orderPartition = Partitioner.Create(1, count 1, (count / (int)Math.Ceiling((double)Environment.ProcessorCount / 2d))); ParallelOptions parallelOptions = new ParallelOptions(); parallelOptions.MaxDegreeOfParallelism = (int)Math.Ceiling((double)Environment.ProcessorCount / 2d); Parallel.ForEach<Tuple<long, long>, ParallelInitObj>(orderPartition, parallelOptions, () => { Interlocked.Increment(ref fenzu); Debug.WriteLine("开始一个分组,当前分组数为:" fenzu.ToString()); ParallelInitObj initObj = new ParallelInitObj() { mail = new MailHelper(), SumCount = 0, }; return initObj; } , (source, loop, loopIndex, initObj) => { ParallelInitObj curInitObj = initObj; MailHelper mail = curInitObj.mail; string shiyan = String.Format("({0})实验四", Thread.CurrentThread.ManagedThreadId); for (long i = source.Item1; i < source.Item2; i ) { Interlocked.Increment(ref sendCount); if (isReuse) { if (isAsync) { this.SendMessageAsync(mail, false, shiyan, "第" Thread.VolatileRead(ref sendCount) "条", true, true); curInitObj.SumCount ; } else { this.SendMessage(mail, false, shiyan, "第" Thread.VolatileRead(ref sendCount) "条", true, true); curInitObj.SumCount ; } } else { if (isAsync) { this.SendMessageAsync(mail, true, shiyan, "第" Thread.VolatileRead(ref sendCount) "条", true, false); } else { this.SendMessage(mail, true, shiyan, "第" Thread.VolatileRead(ref sendCount) "条", true, false); } } } return curInitObj; } , (initObj) => { ParallelInitObj curInitObj = initObj; if (isReuse) { curInitObj.mail.SetBatchMailCount(curInitObj.SumCount); } Interlocked.Decrement(ref fenzu); Debug.WriteLine("结束一个分组,当前分组数为:" fenzu.ToString()); }); } else { MessageBox.Show("分区发邮件不能为一封"); } #endregion } } /// <summary> /// 同步发送邮件 /// </summary> /// <param name="isSimple">是否只发送一条</param> /// <param name="autoReleaseSmtp">是否自动释放SmtpClient</param> /// <param name="isReuse">是否重用SmtpClient</param> private void SendMessage(MailHelper mail, bool isSimple, string shiyan, string msgCount, bool autoReleaseSmtp, bool isReuse) { AppendReplyMsg(String.Format("{0}:{1}\"同步\"邮件开始。{2}{3}", shiyan, msgCount, watch.ElapsedMilliseconds, Environment.NewLine)); if (!isReuse || !mail.ExistsSmtpClient()) { mail.SetSmtpClient( new SmtpHelper(Config.TestEmailType, false, Config.TestUserName, Config.TestPassword).SmtpClient , autoReleaseSmtp ); } mail.From = Config.TestFromAddress; mail.FromDisplayName = Config.GetAddressName(Config.TestFromAddress); string to = m_to; string cc = m_cc; string bcc = m_bcc; if (to.Length > 0) mail.AddReceive(EmailAddrType.To, to, Config.GetAddressName(to)); if (cc.Length > 0) mail.AddReceive(EmailAddrType.CC, cc, Config.GetAddressName(cc)); if (bcc.Length > 0) mail.AddReceive(EmailAddrType.Bcc, bcc, Config.GetAddressName(bcc)); mail.Subject = m_Subject; // Guid.NewGuid() 防止重复内容,被SMTP服务器拒绝接收邮件 mail.Body = m_Body Guid.NewGuid(); mail.IsBodyHtml = true; if (filePaths != null && filePaths.Count > 0) { foreach (string filePath in FilePaths) { mail.AddAttachment(filePath); } } Dictionary<MailInfoType, string> dic = mail.CheckSendMail(); if (dic.Count > 0 && MailInfoHelper.ExistsError(dic)) { // 反馈“错误 提示”信息 AppendReplyMsg(MailInfoHelper.GetMailInfoStr(dic)); } else { string msg = String.Empty; if (dic.Count > 0) { // 反馈“提示”信息 msg = MailInfoHelper.GetMailInfoStr(dic); } try { if (isSimple) { mail.SendOneMail(); } else { // 发送 mail.SendBatchMail(); } AppendReplyMsg(String.Format("{0}:{1}\"同步\"邮件已发送完成。{2}{3}", shiyan, msgCount, watch.ElapsedMilliseconds, Environment.NewLine)); } catch (Exception ex) { // 反馈异常信息 msg = msg (ex.InnerException == null ? ex.Message : ex.Message ex.InnerException.Message) Environment.NewLine; } finally { // 输出到界面 if (msg.Length > 0) AppendReplyMsg(msg Environment.NewLine); } } mail.Reset(); } /// <summary> /// 异步发送邮件 /// </summary> /// <param name="isSimple">是否只发送一条</param> /// <param name="autoReleaseSmtp">是否自动释放SmtpClient</param> /// <param name="isReuse">是否重用SmtpClient</param> private void SendMessageAsync(MailHelper mail, bool isSimple, string shiyan, string msgCount, bool autoReleaseSmtp, bool isReuse) { AppendReplyMsg(String.Format("{0}:{1}\"异步\"邮件开始。{2}{3}", shiyan, msgCount, watch.ElapsedMilliseconds, Environment.NewLine)); if (!isReuse || !mail.ExistsSmtpClient()) { SmtpClient client = new SmtpHelper(Config.TestEmailType, false, Config.TestUserName, Config.TestPassword).SmtpClient; mail.AsycUserState = String.Format("{0}:{1}\"异步\"邮件", shiyan, msgCount); client.SendCompleted = (send, args) => { AsyncCompletedEventArgs arg = args; if (arg.Error == null) { // 需要注意的事使用 MailHelper 发送异步邮件,其UserState是 MailUserState 类型 AppendReplyMsg(((MailUserState)args.UserState).UserState.ToString() "已发送完成." watch.ElapsedMilliseconds Environment.NewLine); } else { AppendReplyMsg(String.Format("{0} 异常:{1}{2}{3}" , ((MailUserState)args.UserState).UserState.ToString() "发送失败." , (arg.Error.InnerException == null ? arg.Error.Message : arg.Error.Message arg.Error.InnerException.Message) , watch.ElapsedMilliseconds, Environment.NewLine)); // 标识异常已处理,否则若有异常,会抛出异常 ((MailUserState)args.UserState).IsErrorHandle = true; } }; mail.SetSmtpClient(client, autoReleaseSmtp); } else { mail.AsycUserState = String.Format("{0}:{1}\"异步\"邮件已发送完成。", shiyan, msgCount); } mail.From = Config.TestFromAddress; mail.FromDisplayName = Config.GetAddressName(Config.TestFromAddress); string to = m_to; string cc = m_cc; string bcc = m_bcc; if (to.Length > 0) mail.AddReceive(EmailAddrType.To, to, Config.GetAddressName(to)); if (cc.Length > 0) mail.AddReceive(EmailAddrType.CC, cc, Config.GetAddressName(cc)); if (bcc.Length > 0) mail.AddReceive(EmailAddrType.Bcc, bcc, Config.GetAddressName(bcc)); mail.Subject = m_Subject; // Guid.NewGuid() 防止重复内容,被SMTP服务器拒绝接收邮件 mail.Body = m_Body Guid.NewGuid(); mail.IsBodyHtml = true; if (filePaths != null && filePaths.Count > 0) { foreach (string filePath in FilePaths) { mail.AddAttachment(filePath); } } Dictionary<MailInfoType, string> dic = mail.CheckSendMail(); if (dic.Count > 0 && MailInfoHelper.ExistsError(dic)) { // 反馈“错误 提示”信息 AppendReplyMsg(MailInfoHelper.GetMailInfoStr(dic)); } else { string msg = String.Empty; if (dic.Count > 0) { // 反馈“提示”信息 msg = MailInfoHelper.GetMailInfoStr(dic); } try { // 发送 if (isSimple) { mail.SendOneMail(); } else { mail.SendBatchMail(); } } catch (Exception ex) { // 反馈异常信息 AppendReplyMsg(String.Format("{0}\"异步\"异常:({1}){2}{3}", msgCount, watch.ElapsedMilliseconds, ex.Message, Environment.NewLine)); } finally { // 输出到界面 if (msg.Length > 0) AppendReplyMsg(msg Environment.NewLine); } } mail.Reset(); } private void AppendReplyMsg(string msg) { if (this.rtbReply.InvokeRequired) { this.rtbReply.BeginInvoke(new Action<string>(innerAppendMsg), msg); } else { this.rtbReply.AppendText(msg); } } private void innerAppendMsg(string msg) { this.rtbReply.AppendText(msg); } private void btnAttachment_Click(object sender, EventArgs e) { OpenFileDialog fileDialog = new OpenFileDialog(); fileDialog.Multiselect = true; fileDialog.InitialDirectory = Application.StartupPath "\\附件"; if (fileDialog.ShowDialog() == DialogResult.OK) { if (fileDialog.FileNames.Length > 0) { StringBuilder sBuilder = new StringBuilder(this.rtbAttachText.Text); foreach (string filePath in fileDialog.FileNames) { if (sBuilder.Length == 0) sBuilder.Append("当前已选附件有:"); sBuilder.AppendLine().Append(filePath.Substring(filePath.LastIndexOf('\\') 1)); } FilePaths.AddRange(fileDialog.FileNames); this.rtbAttachText.Text = sBuilder.ToString(); } } } private void radioBtn_CheckedChanged(object sender, EventArgs e) { RadioButton curBtn = sender as RadioButton; if (curBtn.Name == "rdoOne") { // 实验一 this.cbbNumber.SelectedIndex = 0; this.cbbNumber.Enabled = false; } else if (curBtn.Name == "rdoTwo") { // 实验二 this.cbbNumber.Enabled = true; } else if (curBtn.Name == "rdoThree") { // 实验三 this.cbbNumber.Enabled = true; } else if (curBtn.Name == "rdoFour") { // 实验四 this.cbbNumber.Enabled = true; } } private void btnClear_Click(object sender, EventArgs e) { // 清空反馈信息 this.rtbReply.Text = String.Empty; } } public class ParallelInitObj { public MailHelper mail { get; set; } public long SumCount { get; set; } } }
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论