我正在尝试制作一个 C# WinForms 应用程序,该应用程序从保存在名为“Links”的表中的 url 中获取数据。每个链接都有一个“上次检查”和“下一次检查”日期时间,并且有一个“间隔”根据上次检查决定“下一次检查”。
现在,我正在做的是在进行网络抓取之前使用查询获取 ID,然后我将 Last Checked 变为 DateTime.Now 并将 Next Check 变为 null 直到所有完成。在网络抓取完成后,两者都会得到更新。
问题是如果正在进行的过程有任何“中止”,lastcheck 将是一个日期,但 nextcheck 将为空。
所以我需要一个更好的方法来让两个进程不在同一个表的同一行上工作。但不确定如何。
最佳答案
对于多线程解决方案,标准的工程方法是使用工作池和工作池。
这只是一个概念草图 - 您应该根据自己的情况进行调整:
- 工作人员(即线程)查看工作池。如果有一些可用的工作,它会将其标记为
in_progress
。必须这样做,以便没有两个线程可以承担相同的工作。例如,您可以在 C# 中使用lock
在数据库中执行查询,并在返回前标记一行。 - 您需要有一种方法可以在线程结束后取消标记它。成功与否,必须重新设置
in_progress
。通常,您可以使用finally
block ,这样您就不会在出现任何异常时错过它。 - 如果没有可用的工作,线程将进入休眠状态。
- 每当新工作到达时(即
INSERT
,或nextcheck
到期),其中一个休眠线程就会被唤醒。 - 当您的程序启动时,它应该清除所有
in_progress
标志以防上一次崩溃。 - 您应该利用 DBMS 事务,以便工作人员在完成其工作后所做的任何更改都是原子的 - 即其他线程会在它们同时发生时感知它们。
通过更改工作池的大小,您可以设置同时活跃的工作人员的最大数量。
关于c# - 如何避免同时在表上工作的两个(或更多)线程不在同一行上工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46845081/