Поскольку отправка электронных писем является процессом, связанным с вводом-выводом, поэтому создание потоков для отправки электронных писем не приведет к значительному ускорению (если вообще будет).
Если вы используете SMTP-сервер, который является частью Windows, то, когда вы «отправляете» электронное письмо, оно фактически не отправляется в этот момент. Он стоит в очереди на сервере, и сервер отправляет их так быстро, как только может. Отправка электронных писем на самом деле является медленным процессом.
Я думаю, что я говорю, что есть два варианта:
- Просто отправьте их последовательно и посмотрите, соответствует ли это вашим требованиям к производительности.
- Вы можете использовать концепцию параллельного программирования под названием «Параллельные данные». Я привел примеры в сообщении блога Параллельные данные — параллельное программирование на C#/.NET
По сути, вы получаете все свои данные (за один раз). Причина в том, что получение данных в пакетах также замедлит ваш процесс, поэтому, если вас интересует производительность (именно поэтому я предполагаю, что вы пытаетесь использовать потоки), не делайте многократные обходы сервера базы данных. (который также связан с вводом-выводом на двух уровнях: сетевым вводом-выводом, а также дисковым вводом-выводом).
Так что получите свои данные и разделите их на куски или разделы. Все это описано в статье, на которую я указал. Наивной реализацией было бы количество чанков, равное количеству ядер на машине.
Каждый чанк обрабатывается одним потоком. Когда все потоки будут выполнены, все готово. Благодаря новым функциям ThreadPool в .NET 4.0 (если вы используете Parallel.For, PLINQ или Tasks) вы получите некоторые другие преимущества, такие как «краже работы» для дальнейшего ускорения работы.
Думаю, Parallel.For/Parallel.ForEach вам подойдет.
ИЗМЕНИТЬ
Только что заметил требование .NET 3.5. Ну, концепции все еще применимы, но у вас нет Parallel.For/ForEach. Итак, вот реализация (измененная из моего сообщения в блоге), которая использует ThreadPool и использует метод Data Parallel.
private static void SendEmailsUsingThreadPool(List<Recipient> recipients)
{
var coreCount = Environment.ProcessorCount;
var itemCount = recipients.Count;
var batchSize = itemCount / coreCount;
var pending = coreCount;
using (var mre = new ManualResetEvent(false))
{
for (int batchCount = 0; batchCount < coreCount; batchCount++)
{
var lower = batchCount * batchSize;
var upper = (batchCount == coreCount - 1) ? itemCount : lower + batchSize;
ThreadPool.QueueUserWorkItem(st =>
{
for (int i = lower; i < upper; i++)
SendEmail(recipients[i]);
if (Interlocked.Decrement(ref pending) == 0)
mre.Set();
});
}
mre.WaitOne();
}
}
private static void SendEmail(Recipient recipient)
{
//Send your Emails here
}
}
class Recipient
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
}
Итак, получите свои данные и вызовите SendEmailUsingThreadPool(), передав ему свои данные. Конечно, не называйте свой метод так :). Если у вас есть DataSet/DataTable, просто измените реализацию, чтобы принять DataSet/DataTable. Этот метод позаботится о разделении ваших данных на куски, поэтому вам не нужно ни о чем беспокоиться. Просто позвоните.
person
Shiv Kumar
schedule
24.02.2011