c# - 使用 Entity Framework 构建一个简单的多线程时事通讯引擎

标签 c# multithreading entity-framework

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

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

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

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

最佳答案

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

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

在一个工作单元下

  • 读取 N x 条记录,使用悲观锁定(即防止拉取相同电子邮件的其他线程并发读取)
  • 用批处理 ID(或 IsProcessed 指示符)标记这些记录
  • 将记录返回给您的应用

例如SQL Server 中的批处理 PROC 可能类似于(假设表 = 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()。

关于c# - 使用 Entity Framework 构建一个简单的多线程时事通讯引擎,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12131535/

相关文章:

c# - 计算量大的粒子系统用什么技术?

c# - 使用隐式数组初始值设定项作为 C# 属性参数编译错误

java - 优先获取可能被锁定的公平 ReentrantLock

c# - 需要 self 跟踪实体和 POCO 解释

c# - C#中删除对象后如何完全清除内存

c# - 在跨线程 WinForm 事件处理中避免 Invoke/BeginInvoke 的困境?

java - 线程响应在 weblogic 部署的应用程序中交换

c# - Entity Framework Core – “Insert if not exists” 可能吗?

wpf - 多种 .NET 技术和模式如何协同工作?

c# - 回文 - 错误