c#中foreach循环内的线程

海家伙,

我有以下代码将不同的邮件发送到我的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

创建队列 – 正如其他人在之前的回复中所建议的那样 – 更加明智和可扩展。

http://msdn.microsoft.com/en-us/library/system.web.configuration.httpruntimesection.executiontimeout.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 } } 

如果您确实认为通过某些multithreading可以提高发送性能,那么您需要手动限制一次创建的线程数,或者使用.Net线程池,因为这样可以排队工作项将阻塞直到线程变为空闲。 这当然比创建显式线程的负载更可取。