Hai guys,
我有以下代码将不同的邮件发送到我的asp.net Web应用程序中的不同用户
foreach (DataRow dataRow in dataTable.Rows)
{
sendMails();
}
public void sendMails()
{
//mail code
}
现在我想在foreach循环中使用线程,但我不知道结果是什么,因为如果我开始'n'线程池中发生什么线程...考虑我的数据表包含1000行,
是否可以同时运行1000个线程?
foreach (DataRow dataRow in dataTable.Rows)
{
ThreadStart ts1 = new ThreadStart(sendMails);
Thread thread1 = new Thread(ts1);
thread1.Start();
}
public void sendMails()
{
//mail code
}
答案 0 :(得分:14)
启动一个可以完成发送所有邮件的线程:
new Thread(() => {
foreach (DataRow dataRow in dataTable.Rows)
{
sendMails();
}
}).Start();
答案 1 :(得分:5)
使用您已经获得的代码,没有将发生在线程池中 - 您将在线程池之外完全创建新线程。
你真的确定要为每封邮件使用一个帖子 - 甚至根本不需要多个线程吗?我想你会受到你与本地SMTP服务器的连接的限制,并且启动多个线程对你没有帮助。
启动单个线程在后台发送所有内容(根据Darin的建议)更明智,如果使用线程的目的是能够向用户返回页面说“是的,我现在正在发送邮件“。另一方面,它确实意味着如果该过程因任何原因而停止,您最终可能只发送了一半。另一种选择(如Charlie所建议的)是使用排队系统(例如文件,数据库或MSMQ)。这样你就可以阻止,直到你排队所有的邮件,这意味着当你返回给用户时你可以确信数据是“安全的” - 但你可以做实际的邮件发送提供更强大服务的背景。
答案 2 :(得分:4)
使用带有单独Windows服务的邮件队列来发送电子邮件会不会更明智?
答案 3 :(得分:1)
不要创建自己的线程,拥有1000个线程将意味着CPU花费所有时间在它们之间切换,并且实际执行任何工作的时间非常短。
使用线程池执行此操作,它将执行最多25个(默认情况下)后台线程,并且可以在它们全部忙碌时自动阻止。
答案 4 :(得分:1)
使用线程池可能更为明智,甚至是.NET 4.0(或并行FX)中的Parallel Linq:
dataTable.Rows.AsParallel().Select(a =>
{
//mail code
return null;
});
答案 5 :(得分:1)
每封电子邮件的线程不是最好的想法,正如许多人所解释的那样,但是如果您决定创建一个后台线程来处理所有电子邮件,则线程运行时间将限制为110秒。 ASP.NET在.NET 2.0中默认将线程执行限制为110秒。 http://msdn.microsoft.com/en-us/library/e1f13641(v=vs.80).aspx
创建队列 - 正如其他人在之前的回复中所建议的那样 - 更加明智和可扩展。
答案 6 :(得分:0)
最好像这样构建你的方法:
public void SendMails(DataTable dt)
{
foreach (DataRow row in dt.Rows)
{
// send emails
}
}
然后像这样称呼它:
SendMails(dataTable);
或者使用BackgroundWorker
调用该方法,以便您的用户界面不会锁定。
答案 7 :(得分:0)
首先,如果您显式创建这样的线程,则不使用线程池。 CLR将通过创建所有这些线程来实现,即使它最终会创建太多并且拖延自己。 1000个显式线程方式太多了。
您是否尝试在另一个线程上执行此操作,因为您希望它以异步方式发生,或者您实际上是否希望多个线程执行发送?
如果是前者,那么尝试类似:
ThreadStart ts1 = new ThreadStart(sendMails);
Thread thread1 = new Thread(ts1);
thread1.Start();
public void sendMails()
{
foreach (DataRow dataRow in dataTable.Rows)
{
//mail code
}
}
如果您确实认为某些多线程会改善发送性能,那么您需要手动限制一次创建的线程数,或使用.Net线程池,因为这样可以让您排队工作项将阻塞直到线程变为空闲。这当然比创建显式线程的负载更可取。