使用块下的互斥体表现不同

时间:2016-09-28 15:15:11

标签: c# .net multithreading

我正在关注线程here这篇文章。在那部分下 Mutex下面的代码就在那里。

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)两次,它应该打印“另一个应用程序实例正在运行。再见!” 。但它不会那么阻止。

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

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

更新

很抱歉误导。我实际上并没有像那篇文章中那样写。

我的代码原样,

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");
        }
    }
}

这再现了我上面解释的问题。如果我删除使用块,它的行为正确。

1 个答案:

答案 0 :(得分:1)

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

当您不使用阻止时,您不需要Dispose互斥锁,因此不要释放互斥锁。当Console.ReadLine语句执行时 - 进程仍然持有互斥锁。当您的流程结束时,互斥锁仍然会被释放,但这不是很好的做法 - 最好总是明确释放互斥锁。

至于为什么它在您发布的第一个代码(更新前)中工作 - Console.ReadLine()语句在内部使用块,因此当此语句上的控制流阻塞时 - 进程仍然保留互斥锁。