By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,911 Members | 1,124 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,911 IT Pros & Developers. It's quick & easy.

A mutex puzzle; single instance of application

P: n/a
See:
http://www.ai.uga.edu/mc/SingleInstance.html

While attempting to use a mutex to allow only one instance of my app to run
at a time (Recipe 4.12 in C# Programmer's Cookbook), I found that if the
mutex is in a local variable in Main(), and my program launches any windows
before Application.Run(), it will lose the mutex upon doing so. It
shouldn't, as far as I can see. Moving the mutex variable outside Main()
and making it static eliminates the problem.

Any ideas? Is there a subtle matter of variable scope and extent that I
haven't understood? Does a process lose its mutexes when it launches a
window? Why?

(The mutex variable still exists, and m.Handle has the same value; but
according to ProcessExplorer, the mutex no longer exists. And all of this
happens only for processes launched from Windows, not under the IDE!)

--

Michael A. Covington - Artificial Intelligence Ctr - University of Georgia

"In the core C# language it is simply not possible to have an uninitialized
variable, a 'dangling' pointer, or an expression that indexes an array
beyond its bounds. Whole categories of bugs that routinely plague C and C++
programs are thus eliminated." - A. Hejlsberg, The C# Programming Language
Nov 15 '05 #1
Share this Question
Share on Google+
20 Replies


P: n/a
Michael A. Covington <lo**@www.covingtoninnovations.com.for.address>
wrote:
See:
http://www.ai.uga.edu/mc/SingleInstance.html

While attempting to use a mutex to allow only one instance of my app to run
at a time (Recipe 4.12 in C# Programmer's Cookbook), I found that if the
mutex is in a local variable in Main(), and my program launches any windows
before Application.Run(), it will lose the mutex upon doing so. It
shouldn't, as far as I can see. Moving the mutex variable outside Main()
and making it static eliminates the problem.

Any ideas? Is there a subtle matter of variable scope and extent that I
haven't understood? Does a process lose its mutexes when it launches a
window? Why?

(The mutex variable still exists, and m.Handle has the same value; but
according to ProcessExplorer, the mutex no longer exists. And all of this
happens only for processes launched from Windows, not under the IDE!)


My guess is that the JIT can notice that the Mutex is no longer
referenced, and thus marks it as available for garbage collection. As a
way of testing this, put the line:

GC.KeepAlive (myMutex);

at the *end* of the Main method.

Let me know if that works, and I'll mention it in the FAQ.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #2

P: n/a
Works for me, could you post your failing Main() method?

Willy.

"Michael A. Covington" <lo**@www.covingtoninnovations.com.for.address> wrote
in message news:OP**************@TK2MSFTNGP11.phx.gbl...
See:
http://www.ai.uga.edu/mc/SingleInstance.html

While attempting to use a mutex to allow only one instance of my app to
run
at a time (Recipe 4.12 in C# Programmer's Cookbook), I found that if the
mutex is in a local variable in Main(), and my program launches any
windows
before Application.Run(), it will lose the mutex upon doing so. It
shouldn't, as far as I can see. Moving the mutex variable outside Main()
and making it static eliminates the problem.

Any ideas? Is there a subtle matter of variable scope and extent that I
haven't understood? Does a process lose its mutexes when it launches a
window? Why?

(The mutex variable still exists, and m.Handle has the same value; but
according to ProcessExplorer, the mutex no longer exists. And all of this
happens only for processes launched from Windows, not under the IDE!)

--

Michael A. Covington - Artificial Intelligence Ctr - University of Georgia

"In the core C# language it is simply not possible to have an
uninitialized
variable, a 'dangling' pointer, or an expression that indexes an array
beyond its bounds. Whole categories of bugs that routinely plague C and
C++
programs are thus eliminated." - A. Hejlsberg, The C# Programming
Language

Nov 15 '05 #3

P: n/a

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Michael A. Covington <lo**@www.covingtoninnovations.com.for.address>
wrote:
See:
http://www.ai.uga.edu/mc/SingleInstance.html

While attempting to use a mutex to allow only one instance of my app to run at a time (Recipe 4.12 in C# Programmer's Cookbook), I found that if the
mutex is in a local variable in Main(), and my program launches any windows before Application.Run(), it will lose the mutex upon doing so. It
shouldn't, as far as I can see. Moving the mutex variable outside Main() and making it static eliminates the problem.

Any ideas? Is there a subtle matter of variable scope and extent that I
haven't understood? Does a process lose its mutexes when it launches a
window? Why?

(The mutex variable still exists, and m.Handle has the same value; but
according to ProcessExplorer, the mutex no longer exists. And all of this happens only for processes launched from Windows, not under the IDE!)


My guess is that the JIT can notice that the Mutex is no longer
referenced, and thus marks it as available for garbage collection. As a
way of testing this, put the line:

GC.KeepAlive (myMutex);

at the *end* of the Main method.

Let me know if that works, and I'll mention it in the FAQ.


I'll try that. Note that inserting additional references to the mutex
variable
(e.g., MessageBox(m.Handle.ToString()) later on in the Main() method did not
help. If the GC thinks I'm no longer using the mutex variable, it's
mistaken.

In any case I'll investigate. Thanks!
Nov 15 '05 #4

P: n/a
So far, the problem is remarkably hard to reproduce, and I don't want to
post the program in which it actually is observed because it's proprietary
(for a client).

But here's a question.

Should there be any difference between this:

Application.Run(new Form1());

and this?

Form1 f1 = new Form1();
f1.Show();
Application.Run();

Would the latter keep the garbage collector from realizing that f1's
variables need to persist even when f1 is not visible?
Nov 15 '05 #5

P: n/a
Dear Jon and others,

Adding GC.KeepAlive(mutex) at the end of the code worked just as well as
making the mutex variable static.

Below is my Main() method, with some names changed to conceal what piece of
software this is. I should add that LaunchFormEdit is not involved in the
cases I'm testing with, and that FormOpeningMenu has a Closing event handler
that calls Application.Exit.

Further wisdom would be welcome!
Michael

[STAThread]
static void Main(string[] args)
{

// 1. Determine that this is the only instance running

bool createdMutex;
System.Threading.Mutex mutex = new
System.Threading.Mutex(true,"asdfasdf",out createdMutex);
// See the GC.KeepAlive below. I don't know why it's necessary.

if (!createdMutex)
{
string msg = "asdfasdfasdf is already running.\r\n\r\n";
System.Windows.Forms.MessageBox.Show(msg,"asdfasdf asdfasdf");
return;
}
// 2. Make a Help Window.
FormHelp formHelp = new FormHelp();
formHelp.Show(); // Without the GC.KeepAlive, the mutex is released
HERE against my wishes.

// 3. Make an Opening Menu.
theOpeningMenu = new FormOpeningMenu();
// 4. Start in either the Opening Menu or FormEdit depending on args.
if (args.Length == 0)
theOpeningMenu.Show();
else
LaunchFormEdit(args[0]);

// 5. Let 'er rip! In either of 2 windows as appropriate.
// They both have Closing event handlers to do Application.Exit() when
the window closes.
Application.Run();
GC.KeepAlive(mutex);
}
Nov 15 '05 #6

P: n/a
Jon,

You got it right. It's a matter of the optimizing compiler outsmarting me.

The optimizing compiler is realizing that there are no operations on the
mutex after a certain point (that can't be moved earlier without affecting
the program), so it's disposing of the mutex much earlier than it ought to.

GC.KeepAlive() fixes it, and this is more elegant (and presumably more
reliable) than my solution involving a static global variable.

Thanks! I'm about to revise the full story, which is on
www.ai.uga.edu/mc/SingleInstance.html.
Michael Covington
Associate Director
Artificial Intelligence Center
The University of Georgia
Nov 15 '05 #7

P: n/a
Not sure it has to do with mutex per se. It is more how your hooking up (or
not) to the message loop AFAICT. The following works as expected from the
perspective that the form is displayed and replies to messages and when you
close the form, the Console writes happen. If you remove the "form2" from
the Application.Run() line, the lines after it, do not run. Test it to see
what I mean. To be safe, I would use the standard means of running
Application.Run(new form()) as not sure of side effects of not doing it.

[STAThread]
static void Main()
{
int myVar = 10;
string myString = "Hello";
Form2 form2 = new Form2();
form2.Show();
Application.Run(form2);
Console.WriteLine("myVar:"+myVar);
Console.WriteLine("myString:"+myString);
Console.ReadLine();
}

--
William Stacey, MVP

"Michael A. Covington" <lo**@www.covingtoninnovations.com.for.address> wrote
in message news:ev**************@TK2MSFTNGP12.phx.gbl...
Jon,

You got it right. It's a matter of the optimizing compiler outsmarting me.
The optimizing compiler is realizing that there are no operations on the
mutex after a certain point (that can't be moved earlier without affecting
the program), so it's disposing of the mutex much earlier than it ought to.
GC.KeepAlive() fixes it, and this is more elegant (and presumably more
reliable) than my solution involving a static global variable.

Thanks! I'm about to revise the full story, which is on
www.ai.uga.edu/mc/SingleInstance.html.
Michael Covington
Associate Director
Artificial Intelligence Center
The University of Georgia

Nov 15 '05 #8

P: n/a

"William Stacey [MVP]" <st***********@mvps.org> wrote in message
news:u1**************@tk2msftngp13.phx.gbl...
Not sure it has to do with mutex per se. It is more how your hooking up (or not) to the message loop AFAICT. The following works as expected from the
perspective that the form is displayed and replies to messages and when you close the form, the Console writes happen. If you remove the "form2" from
the Application.Run() line, the lines after it, do not run. Test it to see what I mean. To be safe, I would use the standard means of running
Application.Run(new form()) as not sure of side effects of not doing it.

[STAThread]
static void Main()
{
int myVar = 10;
string myString = "Hello";
Form2 form2 = new Form2();
form2.Show();
Application.Run(form2);
Console.WriteLine("myVar:"+myVar);
Console.WriteLine("myString:"+myString);
Console.ReadLine();
}


It turns out that my use of Application.Run() was not the problem.
Application.Run() leaves it up to you to create and show all your windows,
and also make sure that the appropriate one (or more) has a Closing event
handler that ends the application (Application.Exit()). This I did. See my
other message for the answer to the mutex problem...
Nov 15 '05 #9

P: n/a
The keep alive may get around the issue and glad it works for. However, try
what I showed to reproduce the same thing without the mutex and you don't
need the keep alive. Not hooking up the form inside the Run() does not seem
to be a good thing. And it may have other side effects we don't see at the
moment.

--
William Stacey, MVP

"Michael A. Covington" <lo**@www.covingtoninnovations.com.for.address> wrote
in message news:OI**************@TK2MSFTNGP11.phx.gbl...

"William Stacey [MVP]" <st***********@mvps.org> wrote in message
news:u1**************@tk2msftngp13.phx.gbl...
Not sure it has to do with mutex per se. It is more how your hooking up (or
not) to the message loop AFAICT. The following works as expected from the perspective that the form is displayed and replies to messages and when

you
close the form, the Console writes happen. If you remove the "form2" from the Application.Run() line, the lines after it, do not run. Test it to

see
what I mean. To be safe, I would use the standard means of running
Application.Run(new form()) as not sure of side effects of not doing it.

[STAThread]
static void Main()
{
int myVar = 10;
string myString = "Hello";
Form2 form2 = new Form2();
form2.Show();
Application.Run(form2);
Console.WriteLine("myVar:"+myVar);
Console.WriteLine("myString:"+myString);
Console.ReadLine();
}


It turns out that my use of Application.Run() was not the problem.
Application.Run() leaves it up to you to create and show all your windows,
and also make sure that the appropriate one (or more) has a Closing event
handler that ends the application (Application.Exit()). This I did. See

my other message for the answer to the mutex problem...

Nov 15 '05 #10

P: n/a
If you mean the "JIT compiler", I agree.
An object reference becomes a candidate for collection as soon as it is no
longer used. A variable that goes out of scope or whose contents can not be
accessed (execution has passed the last use of the variable) is no longer
counted as a live reference by the JITter. This is different when
debugging, the life times of variables will be extended, so that they can be
inspected even after they are (officially) no longer used.

Willy.
"Michael A. Covington" <lo**@www.covingtoninnovations.com.for.address> wrote
in message news:ev**************@TK2MSFTNGP12.phx.gbl...
Jon,

You got it right. It's a matter of the optimizing compiler outsmarting
me.

The optimizing compiler is realizing that there are no operations on the
mutex after a certain point (that can't be moved earlier without affecting
the program), so it's disposing of the mutex much earlier than it ought
to.

GC.KeepAlive() fixes it, and this is more elegant (and presumably more
reliable) than my solution involving a static global variable.

Thanks! I'm about to revise the full story, which is on
www.ai.uga.edu/mc/SingleInstance.html.
Michael Covington
Associate Director
Artificial Intelligence Center
The University of Georgia

Nov 15 '05 #11

P: n/a
Exactly. In the release version of the software, when not running under the
IDE, the variable ceased to exist (and thus the mutex did too) soon after
the last use of the variable. Not instantly, but as soon as there was an
operation that required major rearrangement of memory (opening a new
window).

When debugging under the IDE, the variable didn't cease to exist, because
(of course) the debugger was still using all the variables until they
actually went out of scope.

It turned out that Application.Run() was not the problem. Thanks for your
assistance.

"Willy Denoyette [MVP]" <wi*************@pandora.be> wrote in message
news:%2******************@TK2MSFTNGP09.phx.gbl...
If you mean the "JIT compiler", I agree.
An object reference becomes a candidate for collection as soon as it is no
longer used. A variable that goes out of scope or whose contents can not be accessed (execution has passed the last use of the variable) is no longer
counted as a live reference by the JITter. This is different when
debugging, the life times of variables will be extended, so that they can be inspected even after they are (officially) no longer used.

Willy.
"Michael A. Covington" <lo**@www.covingtoninnovations.com.for.address> wrote in message news:ev**************@TK2MSFTNGP12.phx.gbl...
Jon,

You got it right. It's a matter of the optimizing compiler outsmarting
me.

The optimizing compiler is realizing that there are no operations on the
mutex after a certain point (that can't be moved earlier without affecting the program), so it's disposing of the mutex much earlier than it ought
to.

GC.KeepAlive() fixes it, and this is more elegant (and presumably more
reliable) than my solution involving a static global variable.

Thanks! I'm about to revise the full story, which is on
www.ai.uga.edu/mc/SingleInstance.html.
Michael Covington
Associate Director
Artificial Intelligence Center
The University of Georgia


Nov 15 '05 #12

P: n/a
> It turned out that Application.Run() was not the problem. Thanks for your
assistance.


It was in my testing. When you don't put the form var in application.run,
nothing get run after the form closes (at least with this simple test).
When you include the form in the run(), then the lines following
application.run ran when closing the form. It seems like it just exits
after form close if form var is not inside the run(). Let me know if you
see other behavior.

--
William Stacey, MVP

Nov 15 '05 #13

P: n/a

"William Stacey [MVP]" <st***********@mvps.org> wrote in message
news:eD*************@TK2MSFTNGP12.phx.gbl...
It turned out that Application.Run() was not the problem. Thanks for your assistance.


It was in my testing. When you don't put the form var in application.run,
nothing get run after the form closes (at least with this simple test).
When you include the form in the run(), then the lines following
application.run ran when closing the form. It seems like it just exits
after form close if form var is not inside the run(). Let me know if you
see other behavior.


Everything I've observed is consistent with what Microsoft says:

Application.Run() starts a message loop on the current thread, so that all
the thread's windows will respond to messages. One of them must eventually
execute Application.Exit(), which will stop the message loop and allow
execution to proceed after the Application.Run().

Application.Run(F) does that, and also makes form F visible, and also
provides form F with a Closing event handler that performs
Application.Exit() when the form is closed.

In my application, I'm going to have either of 2 different "main forms"
depending on how it's launched, so I create and show the form myself, and
provide it the appropriate event handler, and then just do an
Application.Run().

After the Application.Exit() executes, the code after Application.Run() is
executed.
Nov 15 '05 #14

P: n/a

"William Stacey [MVP]" <st***********@mvps.org> wrote in message
news:eD*************@TK2MSFTNGP12.phx.gbl...
It turned out that Application.Run() was not the problem. Thanks for your assistance.


It was in my testing. When you don't put the form var in application.run,
nothing get run after the form closes (at least with this simple test).
When you include the form in the run(), then the lines following
application.run ran when closing the form. It seems like it just exits
after form close if form var is not inside the run(). Let me know if you
see other behavior.


Everything I've observed is consistent with what Microsoft says:

Application.Run() starts a message loop on the current thread, so that all
the thread's windows will respond to messages. One of them must eventually
execute Application.Exit(), which will stop the message loop and allow
execution to proceed after the Application.Run().

Application.Run(F) does that, and also makes form F visible, and also
provides form F with a Closing event handler that performs
Application.Exit() when the form is closed.

In my application, I'm going to have either of 2 different "main forms"
depending on how it's launched, so I create and show the form myself, and
provide it the appropriate event handler, and then just do an
Application.Run().

After the Application.Exit() executes, the code after Application.Run() is
executed.
Nov 15 '05 #15

P: n/a
Thanks to all who helped. I've summarized what I learned at:

www.ai.uga.edu/mc/CSharpNotes.html

www.ai.uga.edu/mc/SingleInstance.html
--

Michael A. Covington - Artificial Intelligence Ctr - University of Georgia

"In the core C# language it is simply not possible to have an uninitialized
variable, a 'dangling' pointer, or an expression that indexes an array
beyond its bounds. Whole categories of bugs that routinely plague C and C++
programs are thus eliminated." - A. Hejlsberg, The C# Programming Language
Nov 15 '05 #16

P: n/a
Thanks to all who helped. I've summarized what I learned at:

www.ai.uga.edu/mc/CSharpNotes.html

www.ai.uga.edu/mc/SingleInstance.html
--

Michael A. Covington - Artificial Intelligence Ctr - University of Georgia

"In the core C# language it is simply not possible to have an uninitialized
variable, a 'dangling' pointer, or an expression that indexes an array
beyond its bounds. Whole categories of bugs that routinely plague C and C++
programs are thus eliminated." - A. Hejlsberg, The C# Programming Language
Nov 15 '05 #17

P: n/a
You could actually do that anyway and keep the Application.Run(form) method.
Your forms derive from base Form. So just create a form var of type Form
and set that to the form ref you want to show. You can put that in
Run(form).

int mybool = true;
Form1 form1 = new Form1();
MyForm myForm = new MyForm();
Form form;
if ( mybool )
form = form1;
else
form = myForm;

//Application.Run(new Form1());
Application.Run(form);
Console.WriteLine("Stuff after.");
--
William Stacey, MVP

"Michael A. Covington" <lo**@www.covingtoninnovations.com.for.address> wrote
in message news:us**************@TK2MSFTNGP12.phx.gbl...

"William Stacey [MVP]" <st***********@mvps.org> wrote in message
news:eD*************@TK2MSFTNGP12.phx.gbl...
It turned out that Application.Run() was not the problem. Thanks for your assistance.
It was in my testing. When you don't put the form var in application.run, nothing get run after the form closes (at least with this simple test).
When you include the form in the run(), then the lines following
application.run ran when closing the form. It seems like it just exits
after form close if form var is not inside the run(). Let me know if you see other behavior.


Everything I've observed is consistent with what Microsoft says:

Application.Run() starts a message loop on the current thread, so that all
the thread's windows will respond to messages. One of them must

eventually execute Application.Exit(), which will stop the message loop and allow
execution to proceed after the Application.Run().

Application.Run(F) does that, and also makes form F visible, and also
provides form F with a Closing event handler that performs
Application.Exit() when the form is closed.

In my application, I'm going to have either of 2 different "main forms"
depending on how it's launched, so I create and show the form myself, and
provide it the appropriate event handler, and then just do an
Application.Run().

After the Application.Exit() executes, the code after Application.Run() is
executed.

Nov 15 '05 #18

P: n/a
You could actually do that anyway and keep the Application.Run(form) method.
Your forms derive from base Form. So just create a form var of type Form
and set that to the form ref you want to show. You can put that in
Run(form).

int mybool = true;
Form1 form1 = new Form1();
MyForm myForm = new MyForm();
Form form;
if ( mybool )
form = form1;
else
form = myForm;

//Application.Run(new Form1());
Application.Run(form);
Console.WriteLine("Stuff after.");
--
William Stacey, MVP

"Michael A. Covington" <lo**@www.covingtoninnovations.com.for.address> wrote
in message news:us**************@TK2MSFTNGP12.phx.gbl...

"William Stacey [MVP]" <st***********@mvps.org> wrote in message
news:eD*************@TK2MSFTNGP12.phx.gbl...
It turned out that Application.Run() was not the problem. Thanks for your assistance.
It was in my testing. When you don't put the form var in application.run, nothing get run after the form closes (at least with this simple test).
When you include the form in the run(), then the lines following
application.run ran when closing the form. It seems like it just exits
after form close if form var is not inside the run(). Let me know if you see other behavior.


Everything I've observed is consistent with what Microsoft says:

Application.Run() starts a message loop on the current thread, so that all
the thread's windows will respond to messages. One of them must

eventually execute Application.Exit(), which will stop the message loop and allow
execution to proceed after the Application.Run().

Application.Run(F) does that, and also makes form F visible, and also
provides form F with a Closing event handler that performs
Application.Exit() when the form is closed.

In my application, I'm going to have either of 2 different "main forms"
depending on how it's launched, so I create and show the form myself, and
provide it the appropriate event handler, and then just do an
Application.Run().

After the Application.Exit() executes, the code after Application.Run() is
executed.

Nov 15 '05 #19

P: n/a

"William Stacey [MVP]" <st***********@mvps.org> wrote in message
news:%2******************@tk2msftngp13.phx.gbl...
You could actually do that anyway and keep the Application.Run(form) method. Your forms derive from base Form. So just create a form var of type Form
and set that to the form ref you want to show. You can put that in
Run(form).


Except that I don't want one of my forms to have its Closing event tied to
Application.Exit(). The forms are rigged so that if the main menu launches,
its Closing event is tied to Application.Exit(); but if the edit form is
what we choose to launch, then its Closing event brings up the main menu
rather than exiting the app.
Nov 15 '05 #20

P: n/a

"William Stacey [MVP]" <st***********@mvps.org> wrote in message
news:%2******************@tk2msftngp13.phx.gbl...
You could actually do that anyway and keep the Application.Run(form) method. Your forms derive from base Form. So just create a form var of type Form
and set that to the form ref you want to show. You can put that in
Run(form).


Except that I don't want one of my forms to have its Closing event tied to
Application.Exit(). The forms are rigged so that if the main menu launches,
its Closing event is tied to Application.Exit(); but if the edit form is
what we choose to launch, then its Closing event brings up the main menu
rather than exiting the app.
Nov 15 '05 #21

This discussion thread is closed

Replies have been disabled for this discussion.