我理解多线程和使用线程池的概念。我想弄清楚的一个概念是如何跟踪每个线程上发送的电子邮件。因此,想象一下,每个线程负责提取x个记录,迭代这些电子邮件,应用电子邮件模板,然后将电子邮件保存到提取目录。显然,我需要一种方法来告诉每个线程不要将另一个线程提取相同的数据。
我想到的一个解决方案是分页数据,有一个全局变量或数组来跟踪已发送到的页面,让每个线程检查该变量并从下一个可用页面开始。我能想到的唯一问题是,如果数据发生变化,那么可用的页面可能会不同步。
另一种解决方案是在数据库中设置一个布尔值,以确定是否已通过电子邮件发送帐户。因此,EF会提取X条记录并将这些记录更新为准备发送电子邮件。这样,每个查询只会查找尚未准备好通过电子邮件发送到的电子邮件。
如果可能的话,我想获得一些其他建议,或者扩展我提供的解决方案。
答案 0 :(得分:3)
鉴于您可能有一天想要扩展到多个应用服务器,内存同步实施可能还不足以保证电子邮件不会重复。
解决的最简单方法之一是在数据库级实现批处理机制。
在工作单元下
IsProcessed
指示符) e.g。 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
然后将PROC公开为映射到您的电子邮件实体的EF功能导入。在TransactionScope
ts下,您可以调用EF函数导入,发送电子邮件,并在成功时调用ts.Complete()。
答案 1 :(得分:2)
除了nonnb的方法之外,如果您希望使用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.*
关于将数据库表用作队列,还有一些关于here的重要信息。