簡體   English   中英

如何使用多個線程發送MailMessages?

[英]How can I send MailMessages using multiple threads?

我希望你們會因為線程完全缺乏方向而忍受我。 我必須實現一個郵件隊列處理系統,我必須通過Windows服務發送在數據庫中排隊的電子郵件。

它不是生產者 - 消費者模式。 我一次把10行說成數據。 該數據表包含序列化的MailMessage對象和SMTP發送詳細信息。 如果我必須使用說固定數量的線程(比如6個線程)現在我將如何從線程中的數據表中獲取一行然后發送郵件並再次返回以查看是否還有剩余的行?

實現這一點的任何簡單邏輯都可以,最好用C#中的簡單示例。

我使用的是.NET 3.5

由於發送電子郵件是一個I / O綁定進程,因此生成線程以發送電子郵件將無法實現太多(如果有的話)加速。

如果您正在使用屬於Windows的SMTP服務器,那么當您“發送”電子郵件時,它實際上並不會在該時刻發送。 它位於服務器上的隊列中,服務器盡可能快地發送它們。 發送電子郵件實際上是一個緩慢的過程。

我想我說的是有兩種選擇:

  1. 只需按順序發送它們,看看它是否符合您的性能要求。
  2. 你可以使用一個名為“數據並行”的並行編程概念我在博客文章中用數據並行 - 在C#/ .NET中進行並行編程的例子

基本上,您正在做的是,您將獲得所有數據(一次性完成)。 原因是批量獲取數據也會減慢你的進程,所以如果你對性能感興趣(這就是我猜你試圖使用線程的原因),那么就不要多次前往數據庫服務器(這也是I / O綁定在兩個級別,網絡I / O以及磁盤I / O)。

因此,獲取您的數據,並將其拆分為塊或分區。 這一點在我指出的文章中都有解釋。 天真的實現將是塊的數量等於機器上的核心數量。

每個chunck由一個線程處理。 當所有線程完成后,你就完成了。 借助.NET 4.0中ThreadPool的新功能(如果您使用Parallel.For或PLINQ或任務),您將獲得一些其他好處,例如“偷工作”以進一步加快工作速度。

我認為Parallel.For / Parallel.ForEach對你很有用。

編輯

剛剛注意到.NET 3.5的要求。 那些概念仍然適用,但你沒有Parallel.For / ForEach。 所以這是一個實現(從我的博客文章修改),它使用ThreadPool並使用數據並行技術。

    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。 此方法負責將數據分成塊,因此您不必擔心任何問題。 簡單地稱呼它。

您需要在一個位置將消息提取到內存中,然后將它們路由到單獨的線程。 我猜

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM