首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于互斥类型的WaitOne()方法

关于互斥类型的WaitOne()方法
EN

Stack Overflow用户
提问于 2013-02-14 12:46:31
回答 3查看 7.1K关注 0票数 1

我已经写了一小段代码。类似于下面的内容

代码语言:javascript
复制
    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()。

EN

回答 3

Stack Overflow用户

发布于 2013-02-15 09:01:57

首先,你的意图并不是很清楚。如果你只是想确保许可证不能被两个线程同时设置,你需要这样的东西:

代码语言:javascript
复制
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秒并设置许可,而不管其他线程是否已经完成(基本上就是你在问题中的代码所做的),而不是搞乱互斥锁,你最好这样做(但我很难理解,你为什么要这样做):

代码语言:javascript
复制
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。

票数 2
EN

Stack Overflow用户

发布于 2013-02-15 09:08:21

如果持有AbandondMutexException的进程没有释放它就退出了,那么它将抛出一个will异常。即使使用try/finally块,如果在visual studio中的错误位置停止调试或使用任务管理器结束进程,仍有可能发生这种情况,因此应该重新锁定互斥锁或退出应用程序来处理这种情况。请注意,如果由于抛出的异常而未获得锁,则对release的调用也将抛出。

票数 1
EN

Stack Overflow用户

发布于 2013-02-15 06:32:33

编辑:我后来发现这个答案是不正确的。zespri解释如下。

mutex不可能不被释放,因为它在using块结束时立即被释放。其他任何东西都不能看到mutex,因为它的作用域是该方法。要知道这里有两个独立的Mutex对象,一个在Thread1中,另一个在Thread2中。这是对Mutex的不正确使用。

如果您需要Mutex,请尝试执行以下操作:

代码语言:javascript
复制
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()

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14867968

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档