在dotnet核心中,我如何确保只运行我的应用程序的一个副本?

时间:2017-09-19 14:12:23

标签: singleton .net-core console-application mutex

过去我做过类似的事情

private static bool AlreadyRunning()
{
    var processes = Process.GetProcesses();
    var currentProc = Process.GetCurrentProcess();
    logger.Info($"Current proccess: {currentProc.ProcessName}");
    foreach (var process in processes)
    {
        if (currentProc.ProcessName == process.ProcessName && currentProc.Id != process.Id)
        {
            logger.Info($"Another instance of this process is already running: {process.Id}");
            return true;
        }
    }
    return false;
}

哪个效果很好。在新的dotnet核心世界中,所有内容的进程名称都为dotnet,因此我一次只能运行一个dotnet个应用程序!不是我想要的:D

有没有理想的方式在dotnet中这样做?我看到mutex建议,但我不确定我是否理解在Windows机器以外的其他系统上运行的可能的缺点或错误状态。

2 个答案:

答案 0 :(得分:3)

.NET Core现在支持全局命名的互斥锁。来自PR description,添加了该功能:

  
      
  • 在支持线程进程共享的强大递归互斥锁的系统上,将使用它们
  •   
  • 在其他系统上,使用文件锁。遗憾的是,文件锁在阻塞等待调用中没有超时,我没有找到任何其他具有必要属性的定时等待的同步对象,因此轮询是为了定时等待。
  •   

另外,Named mutex not supported on Unix问题中有一个关于互斥名称的有用说明,应该使用:

  

默认情况下,名称具有会话范围,并且会话在Unix上更精细(每个终端都有自己的会话)。尝试添加" Global"名称的前缀减去引号。

答案 1 :(得分:0)

最后我使用了一个互斥锁,看起来没问题。

我从这里抓起代码 What is a good pattern for using a Global Mutex in C#?

我正在使用的核心版本似乎没有一些安全设置,所以我只是删除它。我相信一切都会好的。 (new Mutex只需要3个参数)

    private static void Main(string[] args)
    {
        LogManager.Configuration = new XmlLoggingConfiguration("nlog.config");
        logger = LogManager.GetLogger("console");
        logger.Info("Trying to start");

        const string mutexId = @"Global\{{guid-guid-guid-guid-guid}}";

        bool createdNew;
        using (var mutex = new Mutex(false, mutexId, out createdNew))
        {
            var hasHandle = false;
            try
            {
                try
                {
                    hasHandle = mutex.WaitOne(5000, false);
                    if (!hasHandle)
                    {
                        logger.Error("Timeout waiting for exclusive access");
                        throw new TimeoutException("Timeout waiting for exclusive access");
                    }
                }
                catch (AbandonedMutexException)
                {
                    hasHandle = true;
                }

                // Perform your work here.
                PerformWorkHere();
            }
            finally
            {
                if (hasHandle)
                {
                    mutex.ReleaseMutex();
                }
            }
        }
    }