我已经写了一小段代码。类似于下面的内容
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()。
发布于 2013-02-15 09:01:57
首先,你的意图并不是很清楚。如果你只是想确保许可证不能被两个线程同时设置,你需要这样的东西:
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互斥锁对象并提供一个名称时,如果具有该名称的系统互斥锁不存在,它将被创建并包装到您获得的.NET对象中。如果之前已经创建了具有此名称的系统互斥锁,那么这个现有互斥锁将被包装并作为新的.NET互斥锁对象返回。
我不认为你应该在你的场景中使用Mutexes。
发布于 2013-02-15 09:08:21
如果持有AbandondMutexException的进程没有释放它就退出了,那么它将抛出一个will异常。即使使用try/finally块,如果在visual studio中的错误位置停止调试或使用任务管理器结束进程,仍有可能发生这种情况,因此应该重新锁定互斥锁或退出应用程序来处理这种情况。请注意,如果由于抛出的异常而未获得锁,则对release的调用也将抛出。
发布于 2013-02-15 06:32:33
编辑:我后来发现这个答案是不正确的。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还是超时。try/finally块,以确保在设置许可证引发异常时释放mutex。嵌套是必需的,因为只有成功调用WaitOne().的线程才能调用ReleaseMetux()
https://stackoverflow.com/questions/14867968
复制相似问题