如果应用程序中有两个线程,并且您不希望它们同时运行某段代码,则只需在这段代码周围加一个锁,如下所示:
lock (someObject) {
// ... some code
}
但是如何在不同的进程之间做同样的事情呢?我认为这就是使用“全局互斥锁”的目的,所以我尝试了各种方法来使用Mutex
类,但它似乎不能满足我的要求,这些要求是:
- 如果您是唯一的示例,请继续运行代码。
- 如果您是第二个示例,请等待第一个示例完成,然后运行代码。
- 不要抛出异常。
我遇到的问题:
- 仅仅在
using(){...}
子句中示例化Mutex
对象似乎没有任何作用;两个示例仍然愉快地同时运行 - 在Mutex上调用
.WaitOne()
会导致第一个示例运行,第二个示例等待,但第二个示例会无限期等待,即使在第一个示例调用.ReleaseMutex()
并离开using(){}
作用域之后也是如此。 .WaitOne()
在第一个进程退出时抛出异常(System.Threading.AbandonedMutexException
)。
不涉及Mutex
的解决方案是非常受欢迎的,特别是因为Mutex
似乎是特定于Windows的。
7条答案
按热度按时间pdtvr36n1#
我有两个应用程序:
ConsoleApplication1.cs
ConsoleApplication2.cs
启动ConsoleApplication1,然后启动ConsoleAplication2,可以完美地工作,没有任何错误。如果您的代码仍然弹出,则是代码的错误,而不是Mutex类的错误。
xsuvu9jc2#
您需要使用一个“已命名的互斥锁”. There is a separate constructor that allows you to define a named mutex。
nzk0hqpo3#
我已经成功地将互斥锁用于这个目的,并且可以确认它是有效的,尽管有一些怪癖。
我有一个完整的工作代码示例在家里。只是张贴评论这个答案,如果你想让我添加代码示例今天晚上。
更新:
这是我的生产应用程序的精简代码。这是一个控制台应用程序,但相同的原则应适用于任何类型的应用程序。使用命令行参数运行
来测试互斥逻辑。
注意,在我的例子中,互斥锁实际上保护了进程的大部分,但是没有理由非要这样使用它,这正是本例所需要的。
c9x0cxw04#
尽管我建议您使用互斥锁并调查问题是否出在代码本身,但一个非常复杂且非常脆弱的替代方法可能是使用“锁定文件”。
基本上,您在文件系统中创建一个临时文件,文件名为两个进程都能识别的名称。如果文件存在,则锁就到位了;另一个进程应该释放任何其他锁,等待,并尝试重新获取。如果文件不存在,则锁不存在;该进程应当创建文件以完成锁定并继续处理,当释放锁定时删除该文件。
正如我所说,它非常复杂和脆弱,但它不使用互斥锁。
或者,使用互斥锁。
6ss1mwsb5#
如果你不想使用互斥锁,我会说使用一个已经存在的文件来滚动你自己的互斥锁会是一个简单的解决方案。如果文件已经存在,就不要启动一个新的互斥锁。但是,你必须处理进程提前终止和文件没有清理的异常情况。
回到互斥锁,这只是一个操作系统的“对象”,因为没有一个更好的术语。你真的需要在你使用的每个操作系统上都有这样的东西。我相信其他的.net clr也会允许你访问那些系统原语。我只是用一个定义好的程序集来 Package 它们,这个程序集在每个平台上都可能是不同的。
希望这是有道理的。
kgqe7b3p6#
我不得不在一个表单应用程序中完成这一操作,简单但工作正常。
wh6knrhe7#
也许我过于简化了这个问题,但是我以前只是检查了进程名称。
您可以使用此函数等待其他进程完成,然后运行当前进程。