c#使用单个Mutex控制多个线程的Windows服务

本文关键字:线程 Windows 服务 控制 单个 Mutex | 更新日期: 2023-09-27 18:29:38

我有一个创建多个线程的Windows服务;每个线程在功能上是相同的,但指向不同的服务器进行处理。但是,每个线程也从主服务器上的accounts表中读取一些数据。

我还有一个控制台应用程序,它将记录插入、更新和删除到所有线程都要查看的accounts表中

我需要做的是在控制台应用程序运行时让所有服务线程停止处理——控制台应用程序需要等到所有线程暂停后才能开始做任何事情。当控制台应用程序完成时,线程需要继续处理。我想我可以使用以下逻辑使用两个互斥:

  1. 当服务启动时,它获得"服务"互斥锁上的锁表示它正在运行,然后创建并启动线程。

  2. 当控制台应用程序启动时,它获得"account"互斥说它正在运行。

  3. 控制台应用程序然后等待"服务"互斥体,直到它释放。

  4. 在每次处理过程中,服务的每个线程都会检查"account"互斥,检查是否声明了互斥。如果"account"互斥被声明,线程请求服务释放"服务"互斥,然后等待"帐户"互斥。

  5. 控制台应用程序进行处理。

  6. 控制台应用程序释放"account"互斥锁,然后关闭。

  7. 释放"account"互斥后,服务线程将继续,并且要求服务获取"服务"互斥。

我的问题是,我不知道如何让线程获得服务来获得或释放"服务"互斥。

我试着把互斥锁放进去了。WaitOne()/mmutex。ReleaseMutex()在Service.cs中的静态方法中,但它们(显然)在线程上下文中执行(因此,由于试图释放线程不拥有的互斥体,释放会引发异常——我想WaitOne还会在线程声明互斥体时进一步导致错误)。

正确的方法是什么?我可以在线程中做些什么来让服务获取/释放互斥体吗?我应该使用其他东西而不是互斥锁吗?

c#使用单个Mutex控制多个线程的Windows服务

我认为在这里的任何方法中,竞争条件都是一个真正的问题。但一种可能的、更简单的方法是在数据库中使用控制表。其中有两个字段:一个线程计数器,在每个线程开始/结束后升高和降低,另一个标志指示控制台何时运行——每个线程在运行和升高计数器之前都会首先检查。然后控制台将检查线程计数器是否为零(通过彗星轮询或sql依赖项)。

至少使用这种方法,您可以从外部观察线程在做什么,并根据您何时设置标志/计数器来缓解竞争条件。(当然,如果你的服务或控制台应用程序崩溃,你会有脏数据,但清理控制表是没有意义的)

然而,如果你确实想要实时处理,那么将两者合并为一个服务是可行的。。。

尽量避免通过互斥来控制/同步工作管理器服务(windows服务)和控制台应用程序。而是将控制台应用程序合并到windows服务中。

一种方法是让windows服务公开一个wcf服务,控制台应用程序可以使用该服务来调用以前在控制台应用程序本身中的代码。(我认为控制台应用程序允许人工干预)

现在,所有需要同步的代码/线程都在同一个进程中。

在这里,您可以使用read-writer锁进行同步,以前从控制台应用程序调用的代码将是写入程序,在操作过程中需要独占访问,服务线程将获得读取器访问权限(并且可以同时读取)。

如果控制台应用程序也需要执行读取访问,并且有条件地只执行更新,那么您可以获得可升级的锁。