1

我了解多线程和使用线程池的概念。我试图弄清楚的一个概念是如何跟踪每个线程上发送的电子邮件。所以想象一下,每个线程负责提取 x 条记录,遍历这些电子邮件,应用电子邮件模板,然后将电子邮件保存到提取目录。显然,我需要一种方法来告诉每个线程不要拉取与另一个线程相同的数据。

我想的一个解决方案是对数据进行分页,有一个全局变量或数组来跟踪已经发送到的页面,让每个线程检查该变量并从下一个可用页面开始。我能想到的唯一问题是如果数据发生变化,那么可用页面可能会不同步。

另一种解决方案是在数据库中设置一个布尔值,以确定一个帐户是否已通过电子邮件发送。因此,EF 将提取 X 条记录并将这些记录更新为准备发送电子邮件。这样,每个查询只会查找尚未准备好通过电子邮件发送的电子邮件。

如果可能的话,我想获得一些其他建议,或者扩展我提供的解决方案。

4

2 回答 2

3

鉴于您有一天可能希望扩展到多个应用服务器,内存同步实现也可能不足以保证电子邮件不重复。

最简单的解决方法之一是在数据库级别实现批处理机制。

在一个工作单元下

  • 读取 N x 记录,使用悲观锁定(即防止其他线程同时读取相同的电子邮件)
  • 用批次 ID(或IsProcessed指标)标记这些记录
  • 将记录返回到您的应用程序

例如,SQL 服务器中的批处理 PROC 可能看起来像(假设 table = dbo.Emails,它有一个 PK EmailId 和一个已处理的指示符 BIT 字段IsProcessed):

CREATE PROC dbo.GetNextBatchOfEmails
AS
    BEGIN
        -- Identify the next N emails to be batched. UPDLOCK is to prevent another thread batching same emails
        SELECT top 100 EmailId 
        INTO #tmpBatch
            FROM dbo.Emails WITH (UPDLOCK)
            WHERE IsProcessed = 0

        -- Stamp emails as sent. Assumed that PROC is called under a UOW. The batch IS the UOW
        UPDATE e
            SET e.IsProcessed = 1
            FROM dbo.Emails e
            INNER JOIN #tmpBatch t
                on e.EmailId = t.EmailId

        -- Return the batch of emails to caller
        SELECT e.*
            FROM dbo.Emails e
            INNER JOIN #tmpBatch t
                on e.EmailId = t.EmailId
    END

Then expose the PROC as an EF Function Import mapped to your Email Entity. Under a TransactionScope ts, you can then call the EF Function Import, and send emails, and call ts.Complete() on success.

于 2012-08-26T16:01:56.377 回答
2

In addition to nonnb's method, you can accomplish it all in one statement if you wish if you are using SQL Server 2005+.

;WITH q AS
(
   SELECT TOP 10 * 
   FROM dbo.your_queue_table
   WHERE
       IsProcessing = 0
   --you can obviously include more filtering criteria to meet your needs
)

UPDATE q WITH (ROWLOCK, READPAST)
SET IsProcessing = 1
OUTPUT INSERTED.*

There is also some great information located here about using database tables as queues.

于 2012-08-26T16:27:30.450 回答