Потоки в цикле foreach в c#

Парни Hai,

У меня был следующий код, чтобы отправить различные письма differnt пользователям в моем веб-приложении asp.net

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

Теперь я хочу использовать потоки в цикле foreach, но я не знаю то, что было бы результатом потому что, если я запускаю 'n' количество потоков, что происходит с пулом потоков.. Полагайте, что моя таблица данных содержит 1 000 строк,

Действительно ли возможно иметь 1 000 потоков, работающих одновременно?

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

public void sendMails()
{
   //mail code
}
6
задан ACP 5 January 2010 в 11:23
поделиться

8 ответов

Запустите один поток, который будет выполнять работу по отправке всех писем:

new Thread(() => {
    foreach (DataRow dataRow in dataTable.Rows) 
    {
        sendMails();
    }
}).Start();
14
ответ дан 8 December 2019 в 04:08
поделиться

Используя имеющийся у вас код, ничего не случилось бы с пулом - вы бы создавали новые потоки полностью за пределами пула.

Вы действительно уверены, что хотите использовать поток на одно письмо - или даже несколько потоков вообще? Я полагаю, что вы будете ограничены вашим подключением к локальному SMTP-серверу, и запуск нескольких потоков не поможет в этом.

Запуск одного потока для отправки всего в фоновом режиме (по предложению Дарина) является более разумным, если целью использования потоков является возможность вернуть пользователю страницу, говорящую: "Да, теперь я отправляю почту". С другой стороны, это означает, что если этот процесс по какой-то причине прекратится, то в конечном итоге вы сможете отправить только половину из них. Альтернативой (как предложил Чарли) было бы использование системы очереди (например, файл, база данных или MSMQ). Таким образом, вы могли бы блокировать до тех пор, пока не поставите в очередь все письма, что означает, что когда вы возвращаетесь к пользователю, вы можете быть уверены, что данные "в безопасности" - но вы можете делать фактическую отправку почты в фоновом режиме с помощью сервиса, который может быть более надежным.

.
5
ответ дан 8 December 2019 в 04:08
поделиться

Разве не разумнее было бы посмотреть на использование очереди сообщений с отдельным сервисом windows для отправки сообщений?

4
ответ дан 8 December 2019 в 04:08
поделиться

Не создавайте собственные потоки, наличие 1000 потоков будет означать, что процессор будет тратить все свое время на переключение между ними и очень мало времени на реальное выполнение какой-либо работы.

Используйте для этого потоковый пул, он будет выполнять до 25 (по умолчанию) фоновых потоков и может автоматически блокировать, когда все они заняты.

Смотрите MSDN tutorial

1
ответ дан 8 December 2019 в 04:08
поделиться

Поток на электронную почту - не самая лучшая идея, так как многие объясняют, почему, однако, в случае, если вы решили создать один фоновый поток для обработки всех писем, время работы потока будет ограничено 110 секундами. ASP.NET по умолчанию ограничивает время выполнения потока 110 секундами в .NET 2.0. 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

1
ответ дан 8 December 2019 в 04:08
поделиться

Вероятно, было бы лучше структурировать ваш метод следующим образом:

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

А затем вызывать его следующим образом:

SendMails(dataTable);

Или вызывать метод с помощью BackgroundWorker, чтобы ваш пользовательский интерфейс не был заблокирован.

.
0
ответ дан 8 December 2019 в 04:08
поделиться

Первый момент заключается в том, что если вы явно создаете такие потоки, вы не используете пул потоков. 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, так как это позволит вам ставить в очередь рабочие элементы, которые будут блокироваться до тех пор, пока поток не станет свободным. Это, безусловно, предпочтительнее, чем создавать нагрузки явных потоков.

.
0
ответ дан 8 December 2019 в 04:08
поделиться
[

] Возможно, для этого было бы разумнее использовать Thread Pool или даже Parallel Linq, который поставляется в .NET 4.0 (или в Parallel FX):[

]. [
dataTable.Rows.AsParallel().Select(a =>
{
    //mail code
    return null;
});
]
1
ответ дан 8 December 2019 в 04:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: