首页新闻找找看学习计划

一段忧患很深的代码

0
悬赏园豆:30 [已解决问题] 解决于 2013-09-23 13:51
 1 if (!MessageQueue.Exists(@".\private$\tms_3pl_EmailSend"))
 2                         MessageQueue.Create(@".\private$\tms_3pl_EmailSend");
 3                     MessageQueue myQueue = new MessageQueue(@".\private$\tms_3pl_EmailSend");
 4                     myQueue.SetPermissions("Everyone", System.Messaging.MessageQueueAccessRights.FullControl);
 5                     myQueue.Formatter = new XmlMessageFormatter(types);
 6                     Message[] messages = myQueue.GetAllMessages();
 7                     myQueue.Purge();//清空指定队列的消息
 8                     if (messages != null && messages.Length > 0)
 9                     {
10                         for (int i = 0; i < messages.Length; i++)
11                         {
12                             DoSendEmail dse = new DoSendEmail();
13                             dse.message = messages[i];
14                             Thread th = new Thread(new ThreadStart(dse.SendEmail));
15                             th.Start();
16                         }
17                     }

之前项目结束了,今天我被调到别的项目组协助修改BUG,当然先从熟悉代码开始啦。

当我看到这段多线程发送MSMQ,我觉得隐患很深。

如果messages 很庞大 并且 SendEmail 比较耗时,会引起灾难性后果吧,虽然到目前为止,这个代码运行良好。

我觉得有必要优化一下

DoSendEmail dse1 = new DoSendEmail();
messages.ToList().ForEach(msg => { dse1.message = msg; dse1.SendEmail(); });

干掉了for 循环 里创建线程,我觉得效率要好多了,当然这只是我的看法。

欢迎拍砖,共同进步!

weblogical的主页 weblogical | 初学一级 | 园豆:6
提问于:2013-08-01 18:02
< >
分享
最佳答案
0

只是一个语法的区别 那就别改了。二楼的Task难道就等待着代码非要执行完?我觉得这里更多的不是代码的问题而是机制的问题。

更好的方法就是创建一个线程池,分成若干组,每组特定的任务,发完了之后执行下一批,因为信息的条数不确定特性,短时间特别多呢,如果1000W,难道一个线程也分配200W,一楼代码有可取点,但是不要等待完,要有调度机制,任务执行完了要处理等。。

收获园豆:20
````` | 专家六级 |园豆:14268 | 2013-08-01 20:23

能给个demo学习一下吗?谢谢

weblogical | 园豆:6 (初学一级) | 2013-08-01 20:35
其他回答(2)
0

个人感觉,发邮件这个事,多线程做的话,确实会比单线程效率要高,

但是楼主说的也对,当messages很庞大时,会实例很多的线程出来,

所以,建议这一块,做一个并发控制,控制线程数量,比方说最多同时发送10个邮件~~

收获园豆:2
只会造轮子 | 园豆:2448 (老鸟四级) | 2013-08-01 18:36
 1 //以5个线程为例,每个线程处理200条,假设有1000条记录
 2 int pageSize =200;
 3 Task[] taskArray = new Task[5]; 
 4 for (int i = 0; i < taskArray.Length;i++ )
 5 {
 6       IEnumerable<Message> items = messages.Skip((i - 1) * pageSize).Take(200);
 7       taskArray[i] = Task.Factory.StartNew(() => { items.ToList().ForEach(msg => { DoSendEmail dse1 = new DoSendEmail(); dse1.message = msg; dse1.SendEmail(); }); });
 8                             
 9  }
10  Task.WaitAll(taskArray);
支持(0) 反对(0) weblogical | 园豆:6 (初学一级) | 2013-08-01 19:19

@weblogical: 思路不错,应该可以试试,不过如果不止1000条怎么办.?

应该动态生成Task[]的大小.

Task[] taskArray = new Task[messages.Length/200];

支持(0) 反对(0) 只会造轮子 | 园豆:2448 (老鸟四级) | 2013-08-01 19:51

@发粪图墙: Perfect!

支持(0) 反对(0) weblogical | 园豆:6 (初学一级) | 2013-08-01 20:16
0

用上线程池,然后将邮件做做成队列。设置一个最大线程数~

收获园豆:8
幻天芒 | 园豆:36522 (高人七级) | 2013-08-01 18:47

上面的代码如何?

支持(0) 反对(0) weblogical | 园豆:6 (初学一级) | 2013-08-01 19:20

@weblogical: 没有限制线程的数量。没有用到线程池~

支持(0) 反对(0) 幻天芒 | 园豆:36522 (高人七级) | 2013-08-02 10:57
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册