实例介绍
【实例简介】
【实例截图】
【核心代码】
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小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论