Problem with mutex in release mode

A

Ashutosh

Hi,
I have this code...it works fine in debug mode but not in release mode...

bool bOwnInitially = true;
bool bCreated;
Mutex m = new Mutex(bOwnInitially,
"2ba3dbae-eb22-4712-81e1-638a10a33ab3", out bCreated);
if (!(bCreated && bOwnInitially))
{
MessageBox.Show(Resources.InstanceAlreadyRunning, "My
App", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}

Can someone please tell me what's wrong here?

Regards,
Ashutosh
 
J

Jialiang Ge [MSFT]

Hello Ashutosh

If I understand it rightly, this piece of code is used to enforce a rule
that only one instance of the app process is running. You mentioned that
the code runs fine in debug mode but not in release mode, it's most likely
be caused by the optimization of JIT in release mode. JIT may optimize some
codes or remove some variables that are not used afterwards when the
optimization switch is on. How do you call this piece of code? What's the
output of release mode on your side? I just tested it in a simple winform
project:

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
bool bOwnInitially = true;
bool bCreated;
Mutex m = new Mutex(bOwnInitially,
"2ba3dbae-eb22-4712-81e1-638a10a33ab3", out bCreated);
if (!(bCreated && bOwnInitially))
{
MessageBox.Show(Resources.InstanceAlreadyRunning, "My App",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}

The test project runs as expected (only one instance of the app is allowed)
in both debug and release mode.

Please let me know how you called the code and I will try to find out the
problem. A reproducible project will be very helpful.

==== Additional Resources ====
Single Process Instance Object
http://www.codeproject.com/KB/cs/cssingprocess.aspx


Regards,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

=================================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
=================================================
 
M

Marc Gravell

You need a GC.KeepAlive(m); at the bottom of the code.

Essentially, the optimisations mean that m can legally be garbage
collected at any point after creation (since you don't ever re-read m).
The GC.KeepAlive(m) does nothing except provide an opaque read of the
variable that can't be optimised away.

Marc
 
A

Ashutosh

Thanks for input...

Yes, the object was getting garbage collected and even GC.KeepAlive
didn't solve the issue...

So, I made a root object point to it...the root from which the GC starts
creating the reference tree...

Thanks!!
Ashutosh
 
A

Ashutosh

I was doing exactly the same as you posted....it was getting garbage
collected and even GC.KeepAlive was not solving the issue...
So, I made a root object point to it...
The issue is resolved...

Thanks
Ashutosh
 
J

Jon Skeet [C# MVP]

Ashutosh said:
Thanks for input...

Yes, the object was getting garbage collected and even GC.KeepAlive
didn't solve the issue...

I doubt that very much. GC.KeepAlive works perfectly well, when used
properly. How did you try to use it?
 
J

Jialiang Ge [MSFT]

Thank you Jon and Mark for finding out the reason. I can reproduce the
problem now with this piece of code: (add GC.Collect())

[STAThread]
static void Main()
{
bool bOwnInitially = true;
bool bCreated;
Mutex m = new Mutex(bOwnInitially,
"2ba3dbae-eb22-4712-81e1-638a10a33ab3", out bCreated);
if (!(bCreated && bOwnInitially))
{
MessageBox.Show(Resources.InstanceAlreadyRunning, "My App",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}

GC.Collect();

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}

As for the solution, both GC.KeepAlive and GCHandle.Alloc should help if
they are used properly. For example:

=== GC.KeepAlive ===

[STAThread]
static void Main()
{
bool bOwnInitially = true;
bool bCreated;
Mutex m = new Mutex(bOwnInitially,
"2ba3dbae-eb22-4712-81e1-638a10a33ab3", out bCreated);
if (!(bCreated && bOwnInitially))
{
MessageBox.Show(Resources.InstanceAlreadyRunning, "My App",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());

GC.KeepAlive(m); // keep the obj m alive in main.
}

=== GCHandle.Alloc ===

[STAThread]
static void Main()
{
bool bOwnInitially = true;
bool bCreated;
Mutex m = new Mutex(bOwnInitially,
"2ba3dbae-eb22-4712-81e1-638a10a33ab3", out bCreated);

GCHandle handle = GCHandle.Alloc(m); // allocate gc handle

if (!(bCreated && bOwnInitially))
{
MessageBox.Show(Resources.InstanceAlreadyRunning, "My App",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());

handle.Free(); // release gc handle.
}

Regards,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

=================================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
=================================================
 
A

Ashutosh

I added GC.KeepAlive just before Application.EnableVisualStyles()
I will try again and update.
Thank you all for your help.

Regard,
Ashutosh
 
J

Jon Skeet [C# MVP]

Ashutosh said:
I added GC.KeepAlive just before Application.EnableVisualStyles()
I will try again and update.

No, it needs to be right at the end - otherwise the mutex can be
collected while your app is running, which wil let another instance of
the app be created. The whole point is to keep it alive for the entire
duration of the app.
 
J

Jim Rand

Why don't you create a singleton class that creates a reference to the
Mutex? That way, it won't go out of scope.
 
J

Jon Skeet [C# MVP]

Jim Rand said:
Why don't you create a singleton class that creates a reference to the
Mutex? That way, it won't go out of scope.

A single call to GC.KeepAlive seems a bit simpler to me :)
 
A

Ashutosh

Having GC.KeepAlive after Application.Run(new Form1()) (just having the
code and not executing it) or creating a singleton class or having a
root object point to it. All are basically doing the same thing....it's
telling the GC that there is a reference to the mutex object!!!

Thanks a lot!

Ashutosh
A single call to GC.KeepAlive seems a bit simpler to me :)

--
Regards,
Ashutosh Bhawasinka
email: (e-mail address removed)
MCSA - Messaging,
MCTS - .Net Windows Apps
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top