c# – 使用QueueUserWorkItem在不同的线程上发送电子邮件

c# – 使用QueueUserWorkItem在不同的线程上发送电子邮件,第1张

概述我有一个控制台应用程序,可以向不同的收件人发送自定义的电子邮件(带附件),我想同时发送它们.我需要创建单独的SmtpClients来实现这一点,所以我使用QueueUserWorkItem来创建电子邮件并将它们发送到不同的线程中.  片段 var events = new Dictionary<Guid, AutoResetEvent>();foreach (...){ ThreadP 我有一个控制台应用程序,可以向不同的收件人发送自定义的电子邮件(带附件),我想同时发送它们.我需要创建单独的SmtpClIEnts来实现这一点,所以我使用QueueUserWorkItem来创建电子邮件并将它们发送到不同的线程中.

片段

var events = new Dictionary<GuID,autoresetEvent>();foreach (...){    ThreadPool.QueueUserWorkItem(delegate    {        var ID = GuID.NewGuID();        events.Add(ID,new autoresetEvent(false));        var alert = // create custom class which internally creates SmtpClIEnt & Mail Message        alert.Send();        events[ID].Set();    });   }// wait for all emails to signalWaitHandle.WaitAll(events.Values.ToArray());

我已经注意到(间歇性地)有时并非所有电子邮件都使用上述代码到达特定邮箱.我原本以为使用Send over SendAsync意味着电子邮件肯定是从应用程序发送的.但是,在WaitHandle.WaitAll行之后添加以下代码行:

System.Threading.Thread.Sleep(5000);

似乎工作.我的想法是,无论出于何种原因,仍然没有发送一些电子邮件(即使在Send方法运行之后).给予额外的5秒似乎给应用程序足够的时间来完成.

这可能是我等待发送电子邮件的方式的问题吗?或者这是实际Send方法的问题?一旦我们通过这条线,电子邮件肯定是从应用程序发送的吗?

任何有关此问题的想法都会很棒,似乎无法完全理解实际原因.

更新

这里要求的是SMTP代码:

SmtpClIEnt clIEnt = new SmtpClIEnt("Host");FIEldInfo transport = clIEnt.GetType().GetFIEld("transport",BindingFlags.NonPublic | BindingFlags.Instance);FIEldInfo authModules = transport.GetValue(clIEnt).GetType()    .GetFIEld("authenticationModules",BindingFlags.NonPublic | BindingFlags.Instance);Array modulesArray = authModules.GetValue(transport.GetValue(clIEnt)) as Array;modulesArray.SetValue(modulesArray.GetValue(2),0);modulesArray.SetValue(modulesArray.GetValue(2),1);modulesArray.SetValue(modulesArray.GetValue(2),3);try{    // create mail message    ...    emailClIEnt.Send(emailAlert);}catch (Exception ex){    // log exception}finally{    emailAlert.dispose();}
解决方法 令你烦恼的一件事就是你在线程方法中调用events.Add.字典< TKey,TValue> class不是线程安全的;这段代码不应该在线程内.

更新:我认为ChaosPandion发布了一个很好的实现,但我会让它变得更简单,因此在线程安全性方面没有任何可能出错:

var events = new List<autoresetEvent>();foreach (...){    var evt = new autoresetEvent();    events.Add(evt);    var alert = Createalert(...);    ThreadPool.QueueUserWorkItem(delegate    {                   alert.Send();        evt.Set();    });}// wait for all emails to signalWaitHandle.WaitAll(events.ToArray());

我在这里完全删除了字典,并且所有autoresetEvent实例都是在稍后执行WaitAll的同一个线程中创建的.如果此代码不起作用,那么它必须是电子邮件本身的问题;服务器是丢弃消息(你发送了多少?)或者你试图在Alert实例之间共享一些非线程安全的东西(可能是单例或静态声明的东西).

总结

以上是内存溢出为你收集整理的c# – 使用QueueUserWorkItem在不同的线程上发送电子邮件全部内容,希望文章能够帮你解决c# – 使用QueueUserWorkItem在不同的线程上发送电子邮件所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1248439.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存