.net 如何从数据库表实现多线程队列?

.net 如何从数据库表实现多线程队列?,.net,message-queue,.net,Message Queue,我的过程如下: 用户登录到web应用程序,这会在UserQueue表中删除一个条目 Windows服务每x秒轮询一次此表并处理每个项目 处理后,将从UserQueue表中删除该项 这一切在顺序处理中都能很好地工作,但我担心长时间运行的任务可能会阻塞所有其他用户的队列(这对web应用程序来说是个问题) 我认为.NET中的BlockingCollection将项目保存在内存中,然后对它们进行处理,但我不能保证UserQueue表中的一行不会多次放入该集合(由于BlockingCollection的非

我的过程如下:

  • 用户登录到web应用程序,这会在UserQueue表中删除一个条目
  • Windows服务每x秒轮询一次此表并处理每个项目
  • 处理后,将从UserQueue表中删除该项
  • 这一切在顺序处理中都能很好地工作,但我担心长时间运行的任务可能会阻塞所有其他用户的队列(这对web应用程序来说是个问题)

    我认为.NET中的BlockingCollection将项目保存在内存中,然后对它们进行处理,但我不能保证UserQueue表中的一行不会多次放入该集合(由于BlockingCollection的非唯一性),除非我使用数据库标志(例如BeingProcessed=true)。我不喜欢使用数据库标志,因为如果我的服务因任何原因而停止,它可能会在表中留下未处理的项,其BeingProcessed=true


    是否有一个更标准的方法来解决这个问题,或者我应该考虑Qualth.NET或类似的东西吗?

    < P>基本的技巧是使用一个测试并设置一个日期,而不是仅仅一个简单的布尔值。这是你怎么做到的

    假设您的UserQueue表非常简单。现在是这样的情况:

    create table UserQueue (id integer primary key, description varchar not null)
    
    到目前为止,一切顺利。但我们想安全地抓住一项任务,并用它做些事情

    首先,让我们稍微修改一下模式:

    create table UserQueue (id integer primary key, description varchar not null,
                            dtLocked datetime null)
    
    现在,我们只需遵循一个简单的过程:

  • 寻找我们可以通过
    select*from UserQueue limit 1
  • 尝试锁定它,将时间戳设置为
    NOW()
    ,其中它当前为空,例如通过
    updateuserqueue set dtLocked=NOW(),其中id=@id,dtLocked为空
  • 仅当至少更新了一行时才继续
  • 因为我们现在使用的锁是
    datetime
    ,所以我们可以通过简单的update语句定期清理死掉的任务,该语句删除超过一定时间(比如五分钟)的锁


    作为奖励,此设计允许您同时安全地处理多个任务,因此您可以通过简单地启动更多线程来消除任何用户任务阻塞的机会。

    虽然您的问题可能会从数据库事务中受益,但我不确定您是否会从具有相同项目排队的长时间运行的进程中获益匪浅。对于这种情况,我建议找到一个对提交的数据有意义的更好的主键,以便队列框架按顺序应用影响该行的数据。我还建议研究现有的排队框架,如Microsoft queuing或IBM的MQ(无可否认,我对排队框架不是很精通)。

    这个答案可能会对您有所帮助:更标准的方法是使用适当的消息队列(比如msmq)。我认为你的方法被称为贫民区队列。凯尼也是如此。特别容易设置和使用。感谢Benjamin-这是一个很好的解决方案,可以在不改变架构的情况下快速解决此问题。我开始质疑自己如何处理队列,因为它被基尼称为犹太人区队列;-)此时离开我们的犹太人区队列对我们来说是不合适的——我探索了所有其他的选择,但本杰明的解决方案对我们来说是最好的——所以谢谢!我还输入了一个机器名列,这样我就可以看到哪台机器正在处理队列中的一个项目,这样如果需要的话,我就可以用更多的机器来扩展它