gpt4 book ai didi

c# - 如何使用多线程发送 MailMessages?

转载 作者:行者123 更新时间:2023-11-30 14:40:37 24 4
gpt4 key购买 nike

我希望你们能容忍我在线程方面完全缺乏指导。我必须实现邮件队列处理系统,我必须通过 Windows 服务发送在数据库中排队的电子邮件。

这不是生产者-消费者模式。我一次将 10 行数据提取到一个数据表中。数据表包含序列化的 MailMessage 对象和 SMTP 发送详细信息。如果我必须使用固定数量的线程(比如 6 个线程),现在我将如何在一个线程中从数据表中获取一行,然后发送邮件并再次返回以查看是否还有剩余的行?

实现此目的的任何简单逻辑都可以,最好使用 C# 中的简单示例。

我正在使用 .NET 3.5

最佳答案

由于发送电子邮件是一个 I/O 绑定(bind)过程,因此生成线程来发送电子邮件不会实现太多(如果有的话)加速。

如果您使用的是作为 Windows 一部分的 SMTP 服务器,那么当您“发送”一封电子邮件时,它实际上并没有立即发送。它位于服务器的队列中,服务器会尽可能快地发送它们。发送电子邮件实际上是一个缓慢的过程。

我想我的意思是有两种选择:

  1. 只需按顺序发送它们,看看这是否满足您的性能要求。
  2. 您可以使用称为“Data Parallel”的并行编程概念,我已经在博文 Data Parallel – Parallel Programming in C#/.NET 中举例说明了它。

基本上,您正在做的是,您将获得所有数据(一次性)。原因是批量获取数据也会减慢你的进程,所以如果你对性能感兴趣(这就是为什么我猜你正在尝试使用线程),那么不要多次往返数据库服务器(这也是两个级别的 I/O 绑定(bind),网络 I/O 以及磁盘 I/O)。

因此获取您的数据,并将其拆分为 block 或分区。这一切都在我指向的文章中进行了解释。天真的实现是 block 的数量等于机器上的核心数量。

每个 block 由一个线程处理。当所有线程都完成时,你就完成了。借助 .NET 4.0 中 ThreadPool 的新功能(如果您使用 Parallel.For 或 PLINQ 或 Tasks),您将获得一些其他好处,例如“工作窃取”以进一步加快工作速度。

我认为 Parallel.For/Parallel.ForEach 会很适合你。

编辑

刚注意到 .NET 3.5 要求。这些概念仍然适用,但您没有 Parallel.For/ForEach。所以这是一个使用线程池和数据并行技术的实现(根据我的博客文章修改)。

    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。此方法负责将数据分成 block ,因此您不必担心任何这些。简单地调用它。

关于c# - 如何使用多线程发送 MailMessages?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5101891/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com