没有合适的资源?快使用搜索试试~ 我知道了~
一、需求和初步实现很简单的一个windows服务:客户端连接邮件服务器,下载邮件(含附件)并保存为.eml格式,保存成功后删除服务器上的邮件。实现的伪代码大致如下: 代码如下: public void Process() { var recordCount = 1000;//每次取出邮件记录数 while (true) { using (var client = new Pop3Client()) { //1
资源推荐
资源详情
资源评论
基于一个应用程序多线程误用的分析详解基于一个应用程序多线程误用的分析详解
一、需求和初步实现一、需求和初步实现
很简单的一个windows服务:客户端连接邮件服务器,下载邮件(含附件)并保存为.eml格式,保存成功后删除服务器上的邮
件。实现的伪代码大致如下:
代码如下:
public void Process()
{
var recordCount = 1000;//每次取出邮件记录数
while (true)
{
using (var client = new Pop3Client())
{
//1、建立连接,并进行身份认证
client.Connect(server, port, useSSL);
client.Authenticate(userName, pwd);
var messageCount = client.GetMessageCount(); // 邮箱中现有邮件数
if (messageCount > recordCount)
{
messageCount = recordCount;
}
if (messageCount < 1)
{
break;
}
var listAllMsg = new List<Message>(messageCount); //用于临时保存取出的邮件
//2、取出邮件后填充至列表,每次最多recordCount封邮件
for (int i = 1; i <= messageCount; i++) //邮箱索引是基于1开始的,索引范围: [1, messageCount]
{
listAllMsg.Add(client.GetMessage(i)); //取出邮件至列表
}
//3、遍历并保存至客户端,格式为.eml
foreach (var message in listAllMsg)
{
var emlInfo = new System.IO.FileInfo(string.Format(“{0}.eml”, Guid.NewGuid().ToString(“n”)));
message.SaveToFile(emlInfo);//保存邮件为.eml格式文件
}
//4、遍历并删除
int messageNumber = 1;
foreach (var message in listAllMsg)
{
client.DeleteMessage(messageNumber); //删除邮件(本质上,在关闭连接前只是打上DELETE标签,并没有
真正删除)
messageNumber++;
}
//5、断开连接,真正完成删除
client.Disconnect();
if (messageCount < recordCount)
{
break;
}
}
}
}
开发中接收邮件的时候使用了开源组件Mail.Net(实际上这是OpenSMTP.Net和OpenPop两个项目的并集),调用接口实现很
简单。代码写完后发现基本功能是满足了,本着在稳定的基础上更快更有效率的原则,最终进行性能调优。
二、性能调优及产生二、性能调优及产生BUG分析分析
暂时不管这里的耗时操作是属于计算密集型还是IO密集型,反正有人一看到有集合要一个一个遍历顺序处理,就忍不住有多
线程异步并行操作的冲动。有条件异步尽量异步,没有条件异步,创造条件也要异步,真正发挥多线程优势,充分利用服务器
的强大处理能力,而且也自信中规中矩写了很多多线程程序,这个业务逻辑比较简单而且异常处理也较容易控制(就算有问题
也有补偿措施,可以在后期处理中完善它),理论上每天需要查收的邮件的数量也不会太多,不会长时间成为CPU和内存杀
手,这样的多线程异步服务实现应该可以接受。而且根据分析,显而易见,这是一个典型的频繁访问网络IO密集型的应用程
序,当然要从IO处理上下功夫。
1、收取邮件、收取邮件
从Mail.Net的示例代码中看到,取邮件需要一个从1开始的索引,而且必须有序。如果异步发起多个请求,这个索引怎么传入
呢?必须有序这一条开始让我有点犹豫,如果通过Lock或者Interlocked等同步构造,很显然就失去了多线程的优势,我猜可能
还不如顺序同步获取速度快。
分析归分析,我们还是写点代码试试看效率如何。
快速写个异步方法传递整型参数,同时通过Interlocked控制提取邮件总数的变化,每一个异步方法获取完了之后通过Lock将
Message加入到listAllMsg列表中即可。
邮件服务器测试邮件不多,测试获取一两封邮件,嗯,很好,提取邮件成功,初步调整就有收获,可喜可贺。
2、保存邮件、保存邮件
调优过程是这样的:遍历并保存为.eml的实现代码改为使用多线程,将message.SaveToFile保存操作并行处理,经测试,保
存一到两封邮件,CPU没看出高多少,保存的效率貌似稍有提升,又有点进步。
3、删除邮件、删除邮件
再次调优:仿照多线程保存操作,将遍历删除邮件的代码进行修改,也通过多线程并行处理删除的操作。好,很好,非常好,
这时候我心里想着什么Thread啊,ThreadPool啊,CCR啊,TPL啊,EAP啊,APM啊,把自己知道的能用的全给它用一遍,
挑最好用的最优效率的一个,显得很有技术含量,哇哈哈。
然后,快速写了个异步删除方法开始测试。在邮件不多的情况下,比如三两封信,能正常工作,看起来好像蛮快的。
到这里我心里已经开始准备庆祝大功告成了。
4、产生、产生BUG原因分析原因分析
从上面的1、2、3独立效果看,似乎每一个线程都能够独立运行而不需要相互通信或者数据共享,而且使用了异步多线程技
术,取的快存的快删的也快,看上去邮件处理将进入最佳状态。但是最后提取、保存、删除集成联调测试。运行了一段时间查
看日志,悲剧发生了:
在测试邮件较多的时候,比如二三十封左右,日志里看到有PopServerException异常,好像还有点乱码,而且每次乱码好像
还不一样;再测试三两封信,发现有时能正常工作,有时也抛出PopServerException异常,还是有乱码,分析出错堆栈,是
在删除邮件的地方。
剩余6页未读,继续阅读
资源评论
weixin_38612139
- 粉丝: 3
- 资源: 885
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功