在C#中使用全局互斥锁的好模式是什么?

12 浏览
0 Comments

在C#中使用全局互斥锁的好模式是什么?

Mutex类非常被误解,全局互斥锁更是如此。

在创建全局互斥锁时,有什么好的、安全的模式可以使用?

一个能够工作的模式

  • 无论我的机器所在的区域设置如何
  • 能够确保正确释放互斥锁
  • 可选择地,在未获取到互斥锁时不会永久挂起
  • 处理其他进程放弃互斥锁的情况
0
0 Comments

问题的出现原因是需要在C#中使用全局互斥锁来确保某些代码只能同时运行一个实例。解决方法是创建一个帮助类,通过使用该类可以像使用Lock语句一样使用全局互斥锁。以下是解决方法的代码实现:

using (new SingleGlobalInstance(1000)) //1000ms timeout on global lock
{
    //Only 1 of these runs at a time
    RunSomeStuff();
}
class SingleGlobalInstance : IDisposable
{
    public bool _hasHandle = false;
    Mutex _mutex;
    private void InitMutex()
    {
        string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value;
        string mutexId = string.Format("Global\\{{{0}}}", appGuid);
        _mutex = new Mutex(false, mutexId);
        var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
        var securitySettings = new MutexSecurity();
        securitySettings.AddAccessRule(allowEveryoneRule);
        _mutex.SetAccessControl(securitySettings);
    }
    public SingleGlobalInstance(int timeOut)
    {
        InitMutex();
        try
        {
            if(timeOut < 0)
                _hasHandle = _mutex.WaitOne(Timeout.Infinite, false);
            else
                _hasHandle = _mutex.WaitOne(timeOut, false);
            if (_hasHandle == false)
                throw new TimeoutException("Timeout waiting for exclusive access on SingleInstance");
        }
        catch (AbandonedMutexException)
        {
            _hasHandle = true;
        }
    }
    public void Dispose()
    {
        if (_mutex != null)
        {
            if (_hasHandle)
                _mutex.ReleaseMutex();
            _mutex.Close();
        }
    }
}

这个解决方法可以确保在同一时间只有一个实例可以运行某些代码。通过使用`using`语句,可以在代码块结束时自动释放互斥锁。这样可以避免在使用完互斥锁后忘记释放锁的问题。同时,通过设置超时时间,可以避免死锁的情况。

0
0 Comments

问题的出现原因是:需要确保在多个实例运行时,只有一个实例可以执行某个任务。

解决方法是使用全局互斥锁(Global Mutex)。全局互斥锁是一种同步机制,用于确保在多个进程中只有一个进程可以访问共享资源。在C#中,可以使用Mutex类来实现全局互斥锁。

在上述代码示例中,使用了一个唯一的全局互斥锁ID(mutex_id)来创建Mutex对象。Mutex构造函数的第一个参数指定了是否拥有互斥锁的初始状态,这里设置为false表示不拥有互斥锁的初始状态。第二个参数是互斥锁的ID。

在Main方法中,首先创建了一个Mutex对象,并使用using语句确保在使用完后释放互斥锁。然后通过调用Mutex的WaitOne方法尝试获得互斥锁,如果在5秒内未能获得互斥锁,则表示另一个实例正在运行,输出提示信息并退出程序。

如果获得了互斥锁,就可以执行需要保护的任务。在任务执行完毕后,使用mutex.ReleaseMutex方法释放互斥锁,以便其他实例可以获得互斥锁并执行任务。

通过使用全局互斥锁,可以确保在多个实例运行时,只有一个实例可以执行某个任务,避免了资源竞争和冲突的问题。这种模式可以在需要确保单例运行的应用程序中使用,例如只允许一个实例运行的Windows服务或后台应用程序。

0
0 Comments

使用全局互斥锁的一个好模式是什么?

在C#中使用全局互斥锁是一个非常常见的需求,因为它可以确保在多个线程或进程中只有一个实例可以访问某个资源。然而,正确地使用全局互斥锁并不容易。下面的代码展示了一个在C#中使用全局互斥锁的示例。

代码中首先获取了应用程序的GUID,然后利用这个GUID创建一个唯一的全局互斥锁。在创建互斥锁的过程中,还设置了互斥锁的安全性,以确保多用户环境下的正确使用。

接下来,在使用互斥锁前先判断互斥锁是否已经被其他线程或进程占用。如果互斥锁已经被占用,则等待一段时间后再次尝试获取。如果获取失败,则抛出超时异常。如果互斥锁被其他线程或进程释放,则继续执行后续工作。

最后,在使用完互斥锁后,需要释放互斥锁以便其他线程或进程可以继续使用。

需要注意的是,代码中还提到了一些使用互斥锁的注意事项和技巧。比如,在ASP.NET中使用互斥锁时需要注意线程身份的问题,以及在Unix系统上可能没有类似的实现。

总结起来,使用全局互斥锁的一个好模式是先判断互斥锁是否已经被占用,然后再尝试获取互斥锁,并在使用完互斥锁后及时释放。这样可以确保在多个线程或进程中正确地使用互斥锁,避免资源冲突和竞争条件的发生。

0