using block下的互斥锁的行为不同



我在这里遵循这篇关于线程的文章。在下面的部分互斥,下面的代码有

class OneAtATimePlease
{
  static void Main()
  {
    // Naming a Mutex makes it available computer-wide. Use a name that's
    // unique to your company and application (e.g., include your URL).
    using (var mutex = new Mutex (false, "oreilly.com OneAtATimeDemo"))
    {
      // Wait a few seconds if contended, in case another instance
      // of the program is still in the process of shutting down.
      if (!mutex.WaitOne (TimeSpan.FromSeconds (3), false))
      {
        Console.WriteLine ("Another app instance is running. Bye!");
        return;
      }
      RunProgram();
    }
  }
  static void RunProgram()
  {
    Console.WriteLine ("Running. Press Enter to exit");
    Console.ReadLine();
  }
}

但是当我运行这个代码不像预期的那样,如果我运行两次exe(上面生成的exe),它应该打印"另一个应用程序实例正在运行。再见!"。但是它不会去那个block。

但是,如果我删除using块,代码会按预期正常运行。

请帮帮我。我是线程概念的新手。

抱歉误导。我其实并不完全像那篇文章里写的那样。

我的代码是,

internal class Program
{
    /// <summary>
    /// Entry point
    /// </summary>
    /// <param name="args">The arguments.</param>
    internal static void Main(string[] args)
    {
        //Misc.RunAssemblies();
        var threadingDemo = new ThreadingDemo();
        threadingDemo.MutexDemo();
        Console.ReadLine();
    }
}
namespace LearnNet.Console
{
    using System.Threading;
    public class ThreadingDemo
    {
        public void MutexDemo()
        {
            using (var mutex = new Mutex(false, "Global\oreilly.com OneAtATimeDemo"))
            {
                // Wait a few seconds if contended, in case another instance
                // of the program is still in the process of shutting down.
                if (!mutex.WaitOne(0, false))
                {
                    System.Console.WriteLine("Another app instance is running. Bye!");
                    return;
                }
                RunProgram();
            }
        }
        static void RunProgram()
        {
            System.Console.WriteLine("Running. Press Enter to exit");
        }
    }
}

这再现了我上面解释的问题。如果我删除using块,它会正常工作。

您必须了解互斥是如何工作的。WaitOne获取它,ReleaseMutex 或dispose it释放它。在使用block结束时(当控制流离开它时),互斥锁被dispose(这就是为什么首先存在using block),因此被释放。在您更新的代码中,互斥锁被获取,然后在RunProgram语句后立即释放,并且任何后续实例也立即获取并释放它。

当你不使用using block时,你没有Dispose互斥锁,所以不要释放互斥锁。当Console.ReadLine语句执行时,进程仍然持有互斥锁。当你的进程结束时,互斥锁仍然被释放,但这不是一个很好的做法——最好总是显式地释放互斥锁。

至于为什么它在你发布的第一个代码中工作(更新之前)-有Console.ReadLine()语句在using块内,所以当控制流阻塞在这个语句上时-进程仍然持有互斥锁。

最新更新