处理C#服务中的死锁



我在C#中有一个服务,它从oracle数据库中提取记录并插入MySql数据库,在MySql数据库中成功插入所有记录后,我的oracle数据库的一列会得到更新,即插入了这么多记录。

由于是一项服务,它每5秒就会被调用一次。

我的问题是,在这种情况下,我应该如何处理僵局。就像我的服务从oracle数据库中获取大约20000条记录,并尝试插入MySql数据库大约需要7-8秒,这意味着我的服务将被调用,由于上一个会话的所有记录都没有被插入,所以oracle数据库中不会有更新,下次它将再次获取整个记录,这是我不想要的。

如果可能的话,也提供一些相同的代码。这是纯Window基础服务,而不是WCF。

如果仅在此服务中需要"协调",则使用AutoResetEvent类。

  1. 使用AutoResetEvent实例创建静态字段
  2. 计时器调用的方法应在启动时通过AutoResetEvent.WaitOne(TimeSpan超时)调用检查此实例
  3. 在方法(由计时器调用)结束时,始终调用AutoResetEvent.Set()try{}finally{}构造通常适用于此调用
  4. 在启动服务期间,为创建的实例调用AutoResetEvent.Set()以允许方法(由计时器调用)启动正在工作

使用WaitOne(TimeSpan超时)和小超时允许在前一个定时器尚未完成的情况下快速完成定时器"调用"。。所以你仍然可以每5秒调用你的方法。

在调用其方法之前,肯定需要检查AutoResetEvent的处理,也许还需要一些额外的检查。。。

我不知道您的功能需求是什么,但听起来您并不是真的想在之前的任何运行完成后才开始在服务中进行处理。即,您需要某种系统来判断是否正在进行退出运行,然后在开始后续进程之前进行检查。另一种选择是对请求进行排队,然后将其作为一批处理,有效地消除重复。

听起来您需要等待插入到Oracle中的操作完成,因此在c#中对请求进行排队,即同步执行。研究使用Mutex对象。

我认为这里有几个选项。

  1. 不要频繁地运行服务,尤其是在没有必要的情况下。你说你有一项服务每5秒收集20000条记录——对于这种规模的东西来说,这似乎很频繁
  2. 在Oracle表上发出锁,直到更新完成,这样所有读取操作都必须等待
  3. 不要在计时器上启动服务委派,而是在事件上启动。因此,当你第一次启动服务时,你会手动触发事件,但此后引发的每个事件都会在更新完成后发生

就我个人而言,我更喜欢选择#3。

最新更新