我写了一小段代码。 类似下面的内容
public static void SetLicence1()
{
Console.WriteLine("Setting Aspose Licence in Thread1 ");
Console.WriteLine(SetAsposeLicense());
}
public static void SetLicence2()
{
Console.WriteLine("Setting Aspose Licence in Thread2 ");
Console.WriteLine(SetAsposeLicense());
}
public static bool SetAsposeLicense()
{
try
{
//Declare Mutex variable:
using (Mutex mutex = new System.Threading.Mutex(false, "Test"))
{
mutex.WaitOne(TimeSpan.FromSeconds(5));
var objLic = new License();
objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");
mutex.ReleaseMutex();
}
return true;
}
catch(Exception ex)
{
Console.WriteLine(ex.StackTrace);
return false;
}
}
}
public class TestClass
{
public static void Main()
{
Thread tid1 = new Thread(new ThreadStart(ThreadClass.SetLicence1));
Thread tid2 = new Thread(new ThreadStart(ThreadClass.SetLicence2));
tid1.Start();
tid2.Start();
Console.Read();
}
}
这段代码工作得很好。但是我的问题是,WaitOne()方法是否有可能陷入进程中或跨进程并且互斥对象不会被释放?虽然我使用过mutex.ReleaseMutex()。
答案 0 :(得分:2)
首先,你的意图并不十分明确。如果您只是想确保两个线程无法同时设置许可证,则需要以下内容:
static object s_lock = new object();
public static bool SetAsposeLicense()
{
try
{
lock (s_lock)
{
var objLic = new License();
objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");
}
return true;
}
catch(Exception ex)
{
Console.WriteLine(ex.StackTrace);
return false;
}
}
您注意到此处没有超时5秒。如果你想等待5秒并设置许可,无论,如果另一个线程已经完成(基本上你的问题中的代码是什么),而不是搞乱互斥,你最好这样做(但我难以理解,你为什么要这样做:
private static object s_lock = new object();
public static bool SetAsposeLicense()
{
if (Monitor.TryEnter(s_lock, TimeSpan.FromSeconds(5)))
{
try
{
return SetLicenseInternal();
}
finally
{
Monitor.Exit(s_lock);
}
}
return SetLicenseInternal();
}
public static bool SetLicenseInternal()
{
try
{
var objLic = new License();
objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return false;
}
}
使用Monitor对象比使用互斥锁更加“原生”,因为你不需要交叉处理,所以它更适合这里。
就Mutex而言,它是针对.NET浮出水面system Mutex object的包装器。命名互斥锁是系统范围的,并且在整个过程中可见。当您创建.NET Mutex对象并提供名称时,如果具有此名称的系统Mutex不存在,则会创建它并将其包装到您获得的.NET对象中。如果之前已创建具有此名称的系统Mutex,则此现有Mutex将作为新的.NET Mutex对象进行包装并返回。
我认为你不应该在你的场景中使用互斥锁。
答案 1 :(得分:1)
WaitOne将抛出AbandondMutexException。即使使用try / finally块,如果您在visual studio中的错误位置停止调试或使用任务管理器结束该过程,仍然可能发生这种情况,因此您应该处理此情况重新锁定互斥锁或退出应用程序。请注意,如果由于抛出异常而未获取锁定,则也会抛出对release的调用。
答案 2 :(得分:-1)
编辑:我知道这个答案不正确。 zespri解释如下。
mutex
块没有被释放的可能性,因为using
块一结束就会被释放。没有其他任何东西可以看到mutex
,因为它的范围是该方法。在这里意识到你有两个独立的Mutex
个对象,一个在Thread1中,一个在Thread2中。这只是Mutex
的错误使用。
如果您需要Mutex
,请尝试以下方式:
private static Mutex mutex = new Mutex(false, "Test");
public static bool SetAsposeLicense()
{
try
{
if (!mutex.WaitOne(TimeSpan.FromSeconds(5))
{
throw new TimeoutException("Aspose license registration timed out.");
}
try
{
var objLic = new License();
objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");
return true;
}
finally
{
mutex.ReleaseMutex();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.StackTrace);
return false;
}
}
的变化:
使mutex
成为一个类成员,以便所有线程都可以看到相同的Mutex
。
检查mutex
是否已被释放,或者是否已超时。
如果设置许可证引发异常,则添加嵌套的try/finally
块以确保释放mutex
。嵌套是必需的,因为ReleaseMetux()
只能由成功调用WaitOne()
的线程调用。