我正在编写一个程序,假设在各种类别的时间发送电子邮件到各种电子邮件ID [大约10000]。
static void Main(string[] args)
{
WaitHandle[] waitHandles = new WaitHandle[]
{
new AutoResetEvent(false),
new AutoResetEvent(false),
new AutoResetEvent(false),
new AutoResetEvent(false)
};
ThreadPool.QueueUserWorkItem(new WaitCallback(p.SendMailToCart), waitHandles[0]);
ThreadPool.QueueUserWorkItem(new WaitCallback(p.SendScheduled), waitHandles[1]);
ThreadPool.QueueUserWorkItem(new WaitCallback(p.Mailer), waitHandles[2]);
ThreadPool.QueueUserWorkItem(new WaitCallback(p.BookReviewMail), waitHandles[3]);
.....
.....
}
在此之后,我应该使用.WaitAll:
WaitHandle.WaitAll(waitHandles);
而且,从我在不同线程中调用的方法,我需要调用.Set()方法并通知执行已完成。为..
AutoResetEvent waitHandle = (AutoResetEvent) obj;
waitHandle.Set();
但问题是: 我有四个不同的方法,我在每个单独的线程上调用,并在每个方法中有另一个新的线程,我的代码是:
foreach(DataRow dr in dtEmails.Rows)
{
Thread sendMail = new Thread(delegate()
{
string _emailBody = CreateEmails.CreateEmail();
if (_emailBody.Length > 0)
{
bool result = SendEmail.SendMail(SubjectLine(_subjectline), userID, _emailBody);
if (result == true)
{
Console.WriteLine("> Email sent to {0}", userID);
}
else
{
Console.WriteLine("> Email sending failed for {0}.", userID);
}
}
});
sendMail.Start();
sendMail.IsBackground = true;
}
dtEmails(DataTable最多可包含10000行。)
所以,我没有明白如何使用
AutoResetEvent waitHandle = (AutoResetEvent) obj;
waitHandle.Set();
对于这个问题的解决方案,我找到了一个临时代码:
WaitHandle.WaitAll(waitHandles);
[替换]
while (true)
{
if (ThreadCounter() <= 1)
{
Thread.Sleep(1000 * 30);
Environment.Exit(1);
}
Thread.Sleep(1000 * 30);
}
但我们知道
Thread.Sleep();
浪费CPU时间,我需要一个更好的解决方案。 我在Google上找到了很多解决方案,但它们并不是我所需要的。
编辑:我正在使用SMTP发送电子邮件。
答案 0 :(得分:1)
通过线路发送电子邮件是IO操作。例如,我们可以利用SmtpClient
提供的异步API。这样,我们就不需要生成任何线程,只有在请求完成之前才会阻塞。
为此,我们将使用SmtpClient.SendMailAsync
:
public async Task SendMailsAsync()
{
DataTable dt = new DataTable();
var mailTasks = dt.Rows.OfType<DataRow>().Select(mail =>
{
var smtpClient = new SmtpClient();
return smtpClient.SendMailAsync(new MailMessage(from, to, subject, body));
}).ToArray();
await Task.WhenAll(mailTasks);
}
此方法使用async-await
和任务异步模式。这样,您就不会执行任何冗余线程池线程,并且您可以获得异步IO的好处。
您可以开始使用here。