-1

I want the program dose not run again when it is already running.

the codes are working when i use debugging mode, but are not working with when it release.

the codes as below.

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        string mtxName = "test mutex";
        Mutex mtx = new Mutex(true, mtxName);
        TimeSpan tsWait = new TimeSpan(0, 0, 1);
        bool success = mtx.WaitOne(tsWait);
        if (!success)
        {
            MessageBox.Show("is running.");
            return;
        }

        Application.Run(new Form1());
runRyan
  • 713
  • 1
  • 5
  • 13
  • 1
    See the (currently) second (by votes) answer in the duplicate. You need a global mutex. – sticky bit Dec 28 '20 at 01:30
  • @runRyan I copied your code example, tried to reproduce the issue in the Release cofniguration (have 2 applications started at the same time), but was not able to achieve this. I compiled for AnyCPU, x86 and x64 - no difference, I always get 'is running' message. Please add more details to the question - what .NET framework you use and what is [CLR version](https://stackoverflow.com/questions/1826688/get-current-net-clr-version-at-runtime) (I try with .NET4.6 and CLR 4.0.30319.42000) – fenixil Dec 28 '20 at 01:48
  • @fenixil I think you would write multiple times about application.run(new form1()); right?? – runRyan Dec 28 '20 at 05:36
  • for of all, my main question was why it occurs different way when i use Debug mode and Release mode. – runRyan Dec 28 '20 at 05:40
  • 1
    @runRyan, I don't follow your question about multiple times of application.run, please elaborate. As RossBush pointed out, issue is that you don't hold a reference to your mutex, so it is released and destroyed by GC. Reason, why everything works in Debug mode, is because compiler generates 'safer' code and holds a reference to your mutex in thread stack. In Release this does not happen, because code is more optimized. – fenixil Dec 28 '20 at 06:43

2 Answers2

0

I think you may not be using Mutex for it's intended purpose, a mutex is used to control access to resources to make them 'thread safe', perhaps you should be looking at the process list.

Process myProcess = Process.GetCurrentProcess();
var processExists = Process.GetProcesses().Any(
    p => p.ProcessName.Equals(myProcess.ProcessName) 
    && p.Id != myProcess.Id);
if (processExists)
    return;

However if you really want use mutex, try

    static Mutex mutex = new Mutex(true, "Something unique here");

    [STAThread]
    static void Main()
    {
        if (mutex.WaitOne(TimeSpan.Zero, true))
        {
            try
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }
        else
        {
            MessageBox.Show("is running.");
        }
    }
Xavier
  • 1,383
  • 7
  • 6
  • 1
    _"a mutex is used to control access to resources"_ -- global mutexes are commonly used to control access to the "resource" that is the running program itself, per the actual duplicate to this question. Your suggestion for using the `Process` class is actually quite poor, mainly because of the race condition (two identical processes could try to start at the same time, establish via the same code path that no instance is already running, resulting in both instances remaining running). It's not a reliable way to _guarantee_ only one instance. – Peter Duniho Dec 28 '20 at 01:47
  • This is technically true that the process check could allow processes to co-exist, having said that it would have to be a pretty tight margin between two processes starting for this to occur. Why down vote, I gave a working solution for the Mutex method – Xavier Dec 28 '20 at 04:33
  • 1
    @Xavier, your answer copy-pastes the solution but has nothing to do with the initial question - why code works in the Debug mode, but not in the Release. That's the reason for the downvoting. – fenixil Dec 28 '20 at 06:54
0

Why not use a mutex?

namespace My.Program
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            bool exclusive;
            System.Threading.Mutex appMutex = new System.Threading.Mutex(true, "My.Program", out exclusive);
            if (!exclusive)
            {
                MessageBox.Show("Another instance of My Program is already running.","My Program",MessageBoxButtons.OK,MessageBoxIcon.Exclamation );
                return;
            }
            Application.SetCompatibleTextRenderingDefault(false);
            GC.KeepAlive(appMutex);
            Application.Run(new frmMyMainForm());
        }
    }
}
Ross Bush
  • 14,648
  • 2
  • 32
  • 55
  • 2
    _"Why not use a mutex?"_ -- the OP's code _does_ use a `Mutex`. How does your question _answer_ the original question? – Peter Duniho Dec 28 '20 at 01:44
  • Perhaps nothing is pointing to your Mutex within the same process and the GC will carry it off. Perhaps you are missing -> GC.KeepAlive(appMutex); – Ross Bush Dec 28 '20 at 03:13
  • @RossBush Oh, thanks for your reply and i understand, but i still have a problem why mutex is working when i use debugging mode ? – runRyan Dec 28 '20 at 05:30
  • and one more thing is , is it same mechanism that "announcing global mutex" and "GC.KeepAlive(appMutex)"??? – runRyan Dec 28 '20 at 05:33
  • 1
    @RossBush, [Application.Run](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.application.run?view=net-5.0) is a blocking call, so your solution works just because there is a reference to `appMutex` in the stack what prevents it to be destroyed. This might confuse the reader, so either move it above Application.Run or just release mutex explicitly once Main() exists, eg wrap it into using. Also I'd strongly recommend to add details to your answer why solution from the question is not sufficient (unfortunately question is closed so I can't attach idasm diff) – fenixil Dec 28 '20 at 06:49
  • Doh! I moved it up. – Ross Bush Dec 29 '20 at 00:22