[英]Threads inside a foreach loop in c#
海家伙,
我有以下代码将不同的邮件发送到我的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
}
启动一个可以完成发送所有邮件的线程:
new Thread(() => {
foreach (DataRow dataRow in dataTable.Rows)
{
sendMails();
}
}).Start();
使用你已经获得的代码,线程池不会发生任何事情 - 你将在线程池之外完全创建新线程。
您确定要为每封邮件使用一个帖子 - 甚至是多个线程吗? 我想你会受到与本地SMTP服务器连接的限制,启动多个线程对你没有帮助。
如果使用线程的目的是能够将页面返回给用户说“是的,我现在正在发送邮件”,那么启动单个线程在后台发送所有内容(根据Darin的建议)更为明智。 另一方面,它确实意味着如果该过程因任何原因而停止,您最终可能只发送了一半。 另一种选择(如Charlie所建议的)是使用排队系统(例如文件,数据库或MSMQ)。 这样你就可以阻止,直到你排队所有的邮件,这意味着当你回到用户时你可以确信数据是“安全的” - 但是你可以在后台发送实际的邮件,并提供可能的服务。更健壮。
看一下使用带有单独Windows服务的消息队列来发送电子邮件会不会更明智?
不要创建自己的线程,拥有1000个线程意味着CPU花费所有时间在它们之间切换,而实际执行任何工作的时间都很少。
使用线程池执行此操作,它将执行最多25个(默认情况下)后台线程,并且可以在它们全部忙碌时自动阻止。
请参阅MSDN教程
使用线程池可能更为明智,甚至是.NET 4.0(或并行FX)中的Parallel Linq:
dataTable.Rows.AsParallel().Select(a =>
{
//mail code
return null;
});
每个电子邮件的线程不是最好的想法,正如许多人所解释的那样,但是如果您决定创建一个后台线程来处理所有电子邮件,则线程运行时间将限制为110秒。 ASP.NET在.NET 2.0中默认将线程执行限制为110秒。 http://msdn.microsoft.com/en-us/library/e1f13641(v=vs.80).aspx
创建队列 - 正如其他人在之前的回复中所建议的那样 - 更加合理和可扩展。
构建你的方法可能会更好:
public void SendMails(DataTable dt)
{
foreach (DataRow row in dt.Rows)
{
// send emails
}
}
然后像这样调用它:
SendMails(dataTable);
或者使用BackgroundWorker
调用该方法,以便您的UI不会锁定。
第一点是,如果您显式创建这样的线程,则不使用线程池。 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线程池,因为这样可以排队工作项将阻塞直到线程变为空闲。 这当然比创建显式线程的负载更可取。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.