我如何发送使用多线程MailMessages? [英] How can I send MailMessages using multiple threads?

查看:176
本文介绍了我如何发送使用多线程MailMessages?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望你们会和我一起承担我的情况下,线程的总缺乏方向。 我要实现一个邮件队列处理系统,我必须通过Windows服务来发送电子邮件排队,在数据库中。

I hope you guys will bear with me for my total lack of direction in case of Threading. I have to implement a Mail Queue Processing System where I have to send emails queued up in a database through a Windows Service.

它不是一个生产者 - 消费者图案。我要取说10行的时间为一个确定时代。 该数据表中包含了序列化MailMessage对象和SMTP发送信息。如果非要用说的线程(比如6个线程),固定数量的现在,我将如何去有关从数据表中的一个线程获取行,然后发送邮件,再次返回查看是否有更多的行剩余?

It is not a producer-consumer pattern. I have fetched say 10 rows at a time into a datable. The datatable contains the serialized MailMessage object and SMTP sending details. If I have to use say a fixed number of threads (say 6 threads) Now how would I go about fetching a row from the datatable in a thread and then send the mail and again return to see if any more rows are remaining?

任何简单的逻辑来pferably实现这个会做,$ P $在C#一个简单的例子。

Any simple logic to implement this will do, preferably with a simple example in C#.

我使用.NET 3.5

i am using .NET 3.5

推荐答案

由于发送邮件是I / O限制的过程,所以产生线程发送电子邮件起不到多大(如果有的话)的加速。

Since sending emails is an I/O bound process, so spawning threads to send emails won't achieve much (if any) speedup.

如果您使用的SMTP服务器是Windows的一部分,然后当你发送邮件实际上并没有得到在那个瞬间发送。它坐落在服务器上的队​​列和服务器发送他们尽可能快地就可以了。发送电​​子邮件实际上是一个缓慢的过程。

If you're using the SMTP server that's part of Windows then when you "send" an email it doesn't actually get sent at that instant. It sits in a queue on the server and the server sends them as fast as it can. Sending emails is actually a slow process.

我猜我说的是有两种选择:

I guess what I'm saying is there are two options:

  1. 只要给他们按顺序,看看是否能够满足您的性能需求。
  2. 您可以使用并行编程的概念叫数据并行我在一个博客帖子的数据并行 - 在C#并行编程/ NET

基本上,你在做什么,你会得到所有的数据(一次过)。究其原因,获取数据分批也会减慢你的流程下来,所以如果你有兴趣的表现(这就是为什么我猜你试图使用线程),然后不做多轮前往数据库服务器(这也是I / O限制在两个层面上,网络I / O和磁盘I / O)。

Basically, what you're doing is, you'll get all of your data (in one go). The reason is getting data in batches will also slow your process down so if you're interested in performance (which is why I'm guessing you're attempting to use threads), then don't do multiple rounds trips to the database server (which is also I/O bound on two levels, network I/O as well as disk I/O).

因此​​,让你的数据,并将其分割成块或分区。这是我提出来的文章的所有解释。幼稚实施将组块的数目等于机器上的核心数

So get your data, and split it into chunks or partitions. This is all explained in the article I pointed to. The naive implementation would be the number of chunks equals the number of cores on the machine.

每个chunck由一个线程处理。 当所有的线程都完成了,你就大功告成了。 Withthe在.NET 4.0中的线程池的新功能(如果你使用的Parallel.For或PLINQ或任务),你会得到一些其他的好处,如工作窃取,进一步加快工作。

Each chunck is processed by one thread. When all threads are done, you're done. Withthe new features of the ThreadPool in .NET 4.0 (if you use Parallel.For or PLINQ or Tasks) you'll get some other benefits such as "work stealing" to further speed up the work.

的Parallel.For / Parallel.ForEach会很好地帮助你我会想。

Parallel.For/Parallel.ForEach will work well for you I'd think.

修改

只注意到了.NET 3.5的要求。那么该概念仍然适用,但是你没有的Parallel.For /的ForEach。因此,这里是使用线程池和实现(从我的博客文章修改)使用数据并行技术。

Just noticed the .NET 3.5 requirement. Well the concepts still apply, but you don't have Parallel.For/ForEach. So here is an implementation (modified from my blog post) that uses the ThreadPool and using a Data Parallel technique.

    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中。此方法需要partioning数据分成块的照顾,所以你不必担心任何这一点。简单地调用它。

So, get your data and call SendEmailUsingThreadPool() passing it your data. Of course don't call your method that :). If you have a DataSet/DataTable then simply modify the implementation to accept a DataSet/DataTable. This methods takes care of partioning your data into chunks so you don't have to worry about any of that. Simply call it.

这篇关于我如何发送使用多线程MailMessages?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆