我有一个控制台应用程序,可以向不同的收件人发送自定义的电子邮件(带附件),我想同时发送它们.我需要创建单独的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 signal WaitHandle.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 signal WaitHandle.WaitAll(events.ToArray());
我在这里完全删除了字典,并且所有AutoResetEvent实例都是在稍后执行WaitAll的同一个线程中创建的.如果此代码不起作用,那么它必须是电子邮件本身的问题;服务器是丢弃消息(你发送了多少?)或者你试图在Alert实例之间共享一些非线程安全的东西(可能是单例或静态声明的东西).