简体   繁体   中英

Threads inside a foreach loop in c#

Hai guys,

I had the following code to send different mails to differnt users in my asp.net web application

foreach (DataRow dataRow in dataTable.Rows) 
{
   sendMails();
}
public void sendMails()
{
 //mail code
}

Now i want to use threads inside foreach loop, but i dont know what would be the result because if i start 'n' number of threads what happens to the thread pool.. Consider my datatable contains 1000 rows,

Is it possible to have 1000 threads running concurrently?

foreach (DataRow dataRow in dataTable.Rows) 
{
    ThreadStart ts1 = new ThreadStart(sendMails);
    Thread thread1 = new Thread(ts1);
    thread1.Start();
}

public void sendMails()
{
   //mail code
}

Start a single thread that will do the job of sending all mails:

new Thread(() => {
    foreach (DataRow dataRow in dataTable.Rows) 
    {
        sendMails();
    }
}).Start();

Using the code you've got, nothing would happen to the threadpool - you'd be creating new threads completely outside the threadpool.

Are you really sure you want to use a thread per mail - or even multiple threads at all? I'd imagine you'll be limited by your connection to the local SMTP server, and starting multiple threads isn't going to help that.

Starting a single thread to send everything in the background (as per Darin's suggestion) is more sensible, if the purpose of using threads is to be able to return a page to the user saying "Yes, I'm now sending mails." On the other hand, it does mean that if that process stops for whatever reason, you could end up having only sent half of them. An alternative (as suggested by Charlie) would be to use a queuing system (a file, database or MSMQ for example). That way you could block until you'd queued all the mails, meaning that when you return to the user you can be confident that the data is "safe" - but you could do the actual mail sending in the background with a service which could be more robust.

看一下使用带有单独Windows服务的消息队列来发送电子邮件会不会更明智?

Don't create your own threads, having 1000 threads will mean the CPU spending all it's time switching between them and very little time actually executing any work.

Use the threadpool to do this, it will execute up to 25 (by default) background threads and can automatically block when they're all busy.

See MSDN tutorial

Perhaps would be more sensible to use the Thread Pool for that, or even Parallel Linq, which comes in .NET 4.0 (or in Parallel FX):

dataTable.Rows.AsParallel().Select(a =>
{
    //mail code
    return null;
});

Thread per email is not the best idea as explained why by many, however in case you decided to create one background thread to handle all emails, the thread run time will be limited to 110 seconds. ASP.NET limits thread execution by default to 110 seconds in .NET 2.0. http://msdn.microsoft.com/en-us/library/e1f13641(v=vs.80).aspx

Creating a queue - as suggested by others in earlier replies - is more sensible and scalable.

http://msdn.microsoft.com/en-us/library/system.web.configuration.httpruntimesection.executiontimeout.aspx

It would probably be better to structure your method like this:

public void SendMails(DataTable dt)
{
    foreach (DataRow row in dt.Rows)
    {
        // send emails
    }
}

And then call it like this:

SendMails(dataTable);

Or call the method with a BackgroundWorker so that your UI doesn't lock up.

First point is that if you explicitly create threads like this, you aren't using the thread pool. The CLR will oblige by creating all these threads, even though it'll ultimately create far too many and drag itself down. 1000 explicit threads is way too many.

Are you trying to do this on another thread because you want it to happen asynchronously, or becuase you actually want multiple threads doing the sends?

If the former, then try something like:

ThreadStart ts1 = new ThreadStart(sendMails);
Thread thread1 = new Thread(ts1);
thread1.Start();

public void sendMails()
{
   foreach (DataRow dataRow in dataTable.Rows) 
   {
      //mail code
   }
}

If you do feel that sending performance will be improved with some multithreading, then you'll need to manually throttle the number of threads created at any one time, or use the .Net thread pool, as this will let you queue up work items which will block until a thread becomes free. This is certainly preferable to creating loads of explicit threads.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM