我正在使用此类来防止两个应用程序(一个Windows应用程序和一个在同一OS上运行的Web应用程序)同时使用共享文件。但是我收到错误消息“从未同步的代码块调用了对象同步方法。”
class SharedMutex : IDisposable
{
readonly Mutex mutex;
/// <summary>
/// This function will wait if other thread has owned the mutex
/// </summary>
/// <param name="name"></param>
public SharedMutex(string name)
{
bool m = Mutex.TryOpenExisting(name, out mutex);
if (m)
{
mutex.WaitOne();
}
else
{
mutex = new Mutex(true, name);
}
}
public const string Logs = @"Global\Logs";
public void Dispose()
{
mutex.ReleaseMutex();
mutex.Dispose();
}
}
这就是我使用此类的方式
using (new SharedMutex(SharedMutex.Logs))
{
///access the shared file
}
两个项目中都存在此类。
注意:我不是在寻找访问文件问题的解决方案,我需要知道为什么我的代码有问题。因为我也想将此代码用于其他目的。 谢谢。
答案 0 :(得分:2)
我认为这很可能是由种族状况引起的(如问题注释中的/ u / Sinatr建议)。
以下代码重现了该问题:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
var t1 = Task.Run(func1);
var t2 = Task.Run(func2);
Task.WaitAll(t1, t2);
Console.WriteLine("Done. Press <ENTER>");
Console.ReadLine();
}
static void func1()
{
using (new SharedMutex("test"))
{
Thread.Sleep(2000);
}
}
static void func2()
{
using (new SharedMutex("test"))
{
Thread.Sleep(1000);
}
}
}
class SharedMutex : IDisposable
{
readonly Mutex mutex;
public SharedMutex(string name)
{
bool m = Mutex.TryOpenExisting(name, out mutex);
if (m)
{
mutex.WaitOne();
}
else
{
Thread.Sleep(10); // Simulate a short delay.
mutex = new Mutex(true, name);
}
}
public void Dispose()
{
mutex.ReleaseMutex();
mutex.Dispose();
}
}
}
请注意短暂的延迟Thread.Sleep(10)
,足以在运行调试版本的系统上引发异常。可能必须增加延迟才能引起其他系统上的异常。
如果这确实是问题所在,这是解决方法:
class SharedMutex : IDisposable
{
readonly Mutex mutex;
public SharedMutex(string name)
{
mutex = new Mutex(false, name);
mutex.WaitOne();
}
public void Dispose()
{
mutex.ReleaseMutex();
mutex.Dispose();
}
}
您实际上并不关心它是否是新创建的。 Mutex构造函数会为您解决这个问题。
即使这不是问题,我仍然认为您应该使用上面的实现,因为它没有潜在的竞争条件。
如the documentation for the constructor Mutex(bool, string)
所述:
如果name不为null且initialOwned为true,则调用线程 仅当结果创建了指定的系统互斥锁时,才拥有该互斥锁 这个电话。由于没有机制来确定 创建了命名系统互斥锁,最好将false指定为 调用此构造方法重载时最初拥有。