c#中foreach循环内的线程

时间:2010-01-05 11:23:22

标签: c# asp.net multithreading

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
}

8 个答案:

答案 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个(默认情况下)后台线程,并且可以在它们全部忙碌时自动阻止。

请参阅MSDN tutorial

答案 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

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

http://msdn.microsoft.com/en-us/library/system.web.configuration.httpruntimesection.executiontimeout.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线程池,因为这样可以让您排队工作项将阻塞直到线程变为空闲。这当然比创建显式线程的负载更可取。