all groups > dotnet clr > april 2008 >
You're in the

dotnet clr

group:

Relationship between Application.Exit() and AppDomain



Relationship between Application.Exit() and AppDomain Sunny S
4/4/2008 2:25:00 AM
dotnet clr: Hi,

Does Application.Exit() apply only to the AppDomain in which it is called?
Is it the same as in WPF – a single Application object per AppDomain?
Generally speaking, what is the relationship between an Application object
and AppDomain objects?

Regards,

Re: Relationship between Application.Exit() and AppDomain Scott M.
4/4/2008 10:59:17 AM
One AppDomain per application. One or more AppDomains in a Process.

WPF doesn't change this as WPF is still a .NET application and is still run
by the CLR.

Application.Exit will kill the application you are calling it on and
therefore the AppDomain it is running in.


[quoted text, click to view]

Re: Relationship between Application.Exit() and AppDomain Jon Skeet [C# MVP]
4/4/2008 4:16:35 PM
[quoted text, click to view]

As far as I'm aware, Application.Exit just stops the UI message loop on
the current thread. It doesn't try to do anything to the AppDomain.

A quick experiment *appears* to show that you can't run a WinForms
message loop on the same thread twice, but I could just be missing
something. If you create a new thread for each one though, you can call
Application.Exit in the same AppDomain multiple times perfectly
reasonably:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

public class Test
{
static void Main()
{
for (int i=0; i < 5; i++)
{
Thread t = new Thread(ShowUI);
t.SetApartmentState(ApartmentState.STA);
t.Start(i);
t.Join();

}
}

static void ShowUI(object state)
{
Form form = new Form { Size = new Size(200, 200),
Text = "Form #"+state };
Button b = new Button { Text = "Die!",
Location = new Point(5, 5) };
b.Click += (s, e) => { Application.Exit(); };
form.Controls.Add(b);

Application.Run(form);
}
}

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Re: Relationship between Application.Exit() and AppDomain Willy Denoyette [MVP]
4/4/2008 5:47:31 PM
[quoted text, click to view]


Application.Exit() is a Forms API, WPF does not run a message loop so A.E
makes no sense in WPF.

Willy.
Re: Relationship between Application.Exit() and AppDomain Barry Kelly
4/5/2008 2:50:56 AM
[quoted text, click to view]

That is true.

[quoted text, click to view]

That may be strictly true, but try this on for size:

---8<---
using System;
using System.Windows;
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows.Controls;

public class App
{
[DllImport("user32.dll")]
static extern void PostQuitMessage(int nExitCode);

static Button MakeQuitButton()
{
Button result = new Button();
result.Content = "Quit";
result.Click += (s,e) => PostQuitMessage(0);
return result;
}

[STAThread]
static void Main()
{
new Application().Run(new Window()
{
Content = MakeQuitButton()
});
}
}
--->8---

[quoted text, click to view]

This is empirically false:

---8<---
ntkrnlpa.exe!KiSwapContext+0x2f
ntkrnlpa.exe!KiSwapThread+0x8a
ntkrnlpa.exe!KeWaitForSingleObject+0x1c2
ntkrnlpa.exe!KiSuspendThread+0x18
ntkrnlpa.exe!KiDeliverApc+0x124
ntkrnlpa.exe!KiSwapThread+0xa8
ntkrnlpa.exe!KeWaitForSingleObject+0x1c2
win32k.sys!xxxSleepThread+0x192
win32k.sys!xxxRealInternalGetMessage+0x418
win32k.sys!NtUserGetMessage+0x27
ntkrnlpa.exe!KiFastCallEntry+0xfc
ntdll.dll!KiFastSystemCallRet
USER32.dll!NtUserGetMessage+0xc
WindowsBase.ni.dll+0x5e623
WindowsBase.ni.dll!ResetValue+0xd
WindowsBase.ni.dll!get_SourceProperty+0x1
WindowsBase.ni.dll!.ctor+0xe
WindowsBase.ni.dll!ConvertToString+0x21
WindowsBase.ni.dll!ConvertToString+0x2
PresentationFramework.ni.dll!AlignContent+0x7b
mscorwks.dll!CallDescrWorkerWithHandler+0xa3
mscorwks.dll!MethodDesc::CallDescr+0x19c
mscorwks.dll!MethodDesc::CallTargetWorker+0x1f
mscorwks.dll!MethodDescCallSite::Call_RetArgSlot+0x18
mscorwks.dll!ClassLoader::RunMain+0x263
mscorwks.dll!Assembly::ExecuteMainMethod+0xa6
mscorwks.dll!SystemDomain::ExecuteMainMethod+0x43f
mscorwks.dll!ExecuteEXE+0x59
mscorwks.dll!_CorExeMain+0x15c
mscoree.dll!_CorExeMain+0x2c
KERNEL32.dll!BaseProcessStart+0x23
--->8---

NtUserGetMessage is there, clear as day.

-- Barry

--
Re: Relationship between Application.Exit() and AppDomain Willy Denoyette [MVP]
4/7/2008 3:32:45 PM
[quoted text, click to view]

Well here you are calling PostQuitMessage which doesn't really do what it's
supposed to do, also System.Windows.Forms.Application.Exit doesn't do what
it has to do here (in a WPF based app.). Take a look at the messages using
Spyxx.exe, you'll see that none of the API's are sending WM_QUIT message to
your application. A.E does not terminate the UI thread whereas
PostQuitMessage simply terminates the UI thread and as such the application.
If you are looking for the equivalent of A.E in WPF, then take a look at
Application.Shutdown, PostQuitMessage shouldn't be used at all.

[quoted text, click to view]

Well, above is quite confusing, I should have been more explicit.
Every Windows Application, no matter what the UI framework used , will have
at least one top level window, this is also true for WPF based application.
A minimal WPF application has at least one single Window (HWND) that is used
as a *host* or wrap WPF.
This top level Window, with it's associated message loop and WndProc,
receives/handles all Windows messages for the application, WPF itself is not
HWND based, Windows messages are translated (when appropriate) into CLR
events that get routed to the the WPF Visuals. This top level HWND isn't
exposed and accessible like it is in other frameworks like Windows.Forms,
you can't override WndProc for instance,you shouldn't even assume such
Window is present. Note also that the WPF core registers Windows messages
that aren't know to Windows.Forms and vice-versa, that's why there is an
WPF/Forms interop layer in the form of the HwndHost control.

Willy.
Re: Relationship between Application.Exit() and AppDomain Barry Kelly
4/7/2008 7:08:45 PM
[quoted text, click to view]

PostQuitMessage posts WM_QUIT to the current thread's message queue.
This is no different in a WPF application than in any other Windows
application. WM_QUIT causes GetMessage to return 0.

WindowsBase.dll, System.Windows.Threading.Dispatcher::PushFrameImpl()
contains the message loop which calls GetMessage. It exits the loop when
GetMessage returns 0.

It's a pretty simple stack from there on out to exit the application,
provided you don't have extra code after the Application.Run() call.

---8<---
|> 0:000> !clrstack
|> OS Thread Id: 0x1c68 (0)
|> ESP EIP
|> 0012f358 56d8e623 MS.Win32.UnsafeNativeMethods.GetMessageW(System.Windows.Interop.MSG ByRef, System.Runtime.InteropServices.HandleRef, Int32, Int32)
|> 0012f36c 56d6197e System.Windows.Threading.Dispatcher.GetMessage(System.Windows.Interop.MSG ByRef, IntPtr, Int32, Int32)
|> 0012f3b8 56d617e3 System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
|> 0012f408 56d616c7 System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
|> 0012f424 56d6162d System.Windows.Threading.Dispatcher.Run()
|> 0012f430 5533dce0 System.Windows.Application.RunInternal(System.Windows.Window)
|> 0012f45c 5533db15 System.Windows.Application.Run(System.Windows.Window)
|> 0012f46c 00c5010d App.Main()
--->8---

[quoted text, click to view]

I never said it did.

[quoted text, click to view]

Did you look at the window messages or the thread messages? WM_QUIT
isn't normally sent to the windows, just the thread message queue.

SpyXX on my system crashes when it tries to hook WPF thread messages,
but WinDbg shows the thread message queue calls just fine (as indicated
above).

[quoted text, click to view]

No it doesn't.

It posts a message to the thread message queue and then returns to its
caller immediately.

This can be verified in the debugger, or simply by adding code to the
appropriate places in a sample application:

---8<---
using System;
using System.Windows;
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows.Controls;

public class App
{
[DllImport("user32.dll")]
static extern void PostQuitMessage(int nExitCode);

static Button MakeQuitCButton()
{
Button result = new Button();
result.Content = "Quit";
result.Click += (s,e) =>
{
Console.WriteLine("Before Quit message");
PostQuitMessage(0);
Console.WriteLine("After Quit message");
};
return result;
}

[STAThread]
static void Main()
{
Console.WriteLine("Before Application.Run");
new Application().Run(new Window()
{
Content = MakeQuitCButton()
});
Console.WriteLine("After Application.Run");
}
}
--->8---

This shows the following on my machine, after I press the Quit button:

---8<---
Before Application.Run
Before Quit message
After Quit message
After Application.Run
--->8---

[quoted text, click to view]

I agree with you, one should use Application.Shutdown. You end up
missing out a whole load of app teardown logic if you use
PostQuitMessage.

[quoted text, click to view]

I never asserted that WPF was based on windows all the way down to each
control - that would limit its functionality and performance quite
severely, and you wouldn't get all the scene graph possibilities with
transforms, composing in accelerated hardware etc, without undesirable
clipping. Not even non-WPF applications use windows all the way down,
including IE, Firefox, etc. See also e.g. TGraphicControl in Delphi
(mouse-only input), etc. WPF is in no way new or original in this
respect.

You did, however, appear to assert that WPF applications don't have a
message loop, which is nonsense.

[quoted text, click to view]

There will be at least as many HWNDs as there are separate top-level
windows for that application on the desktop, each one with an
appropriate WNDPROC.

-- Barry

--
Re: Relationship between Application.Exit() and AppDomain Willy Denoyette [MVP]
4/7/2008 10:28:26 PM
[quoted text, click to view]

Well, It doesn't post a WM_QUIT message to the UI's thread queue when run on
Vista (both RTM and SP1), of course it does post WM_QUIT when called in a
Windows.Forms based application (or any non managed windows app.).

[quoted text, click to view]

I know that.

[quoted text, click to view]
SpyXX has some troubles to enumerate "managed" processes when run on 32bit,
and may fail to inject the hook into a managed process on Vista32. The only
combination I found working reliably is: spyxx.exe 64-bit on Vista64 running
with debug privileges. Beware that once SpyXX has failed to run, it will
probably fail until after reboot.


[quoted text, click to view]

It terminates the application without posting a WM_QUIT message on Vista,
instead it sends a private registered message (amongs a bunch of others) to
the dispatcher which finally terminates the session and returns from Run.

[quoted text, click to view]
It doesn't post a WM_QUIT message on Vista. This is different from Windows
Forms which posts a WM_QUIT message (amongs other messages to the UI
thread's queue).


[quoted text, click to view]
Oh, but I never said that the Click handler wasn't called! I only said that
there was no WM_QUIT message posted, sure I should have mentioned "when run
on VISTA!"
Note also that the CLR stack looks somewhat different when run on Vista-64,
the unmanaged stack is also quite different from what you get on Vista32 and
XP.

OS Thread Id: 0x1af4 (0)
Child-SP RetAddr Call Site
000000000064e520 000006422da9f1c1
DomainBoundILStubClass.IL_STUB(System.Windows.Interop.MSG ByRef, Int32,
Int32, Int32, Boolean ByRef)
000000000064e6e0 000006422da9efef
System.Windows.Threading.Dispatcher.GetMessage(System.Windows.Interop.MSG
ByRef, IntPtr, Int32, Int32)
000000000064e790 000006422da9eefe
System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
000000000064e860 000006422a5cc061
System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
000000000064e8c0 000006422a5cbd4d
System.Windows.Application.RunInternal(System.Windows.Window)
000000000064e930 0000064280150187
System.Windows.Application.Run(System.Windows.Window)
000000000064e980 000006427f67ba32 App.Main()

Unmanaged stack..

0:000> kb
RetAddr : Args to Child
: Call Site
00000000`772dd0ce : 0000988e`36afa07e 00000000`006c8bc0 00000000`00000000
00000000`00000000 : USER32!ZwUserGetMessage+0xa
000007fe`fde8589e : 00000000`006c8bc0 00000000`00000001 00000000`00000000
00000642`7f88d142 : USER32!GetMessageW+0x34
00000642`7f679b67 : 00000000`0051ebc0 00000000`006c8bc0 0000988e`37354ec0
00000642`7f3d6ac0 : MSCTF!CThreadInputMgr::GetMessageW+0x42
*** WARNING: Unable to verify checksum for
C:\Windows\assembly\NativeImages_v2.0.50727_64\WindowsBase\3fd6671f329e84b22e22624974ade4a3\WindowsBase.ni.dll
00000642`2da9fc23 : 00000000`1b473cc0 00000000`006c8bc0 00000000`006c8bc0
00000642`2dd2a780 : mscorwks!DoCLRToCOMCall+0x177
00000642`2da9f1c1 : 00000000`0051f190 00000000`0051e9c1 00000000`0051eab8
00000000`0051ebc0 : WindowsBase_ni!GetLocalizedFailureCodeMessage+0xad
Re: Relationship between Application.Exit() and AppDomain Ben Voigt [C++ MVP]
4/8/2008 9:09:20 AM
[quoted text, click to view]

Barry has this one exactly right. PostQuitMessage is a Win32 function, it
couldn't care less whether your app is WPF or WinForms or MFC or whatever.
It posts WM_QUIT and returns.

I don't know how you can get any clearer than this:

http://msdn2.microsoft.com/en-us/library/ms644945(VS.85).aspx
"The PostQuitMessage function posts a WM_QUIT message to the thread's
message queue and returns immediately; the function simply indicates to the
system that the thread is requesting to quit at some time in the future."

Re: Relationship between Application.Exit() and AppDomain Ben Voigt [C++ MVP]
4/8/2008 5:48:03 PM
[quoted text, click to view]

You really should break on PostMessage and PostThreadMessage (A and W
variants), because it's entirely possible that PostQuitMessage did exactly
what the documentation described, but the .NET method (Application.Shutdown
I guess) triggered ending the message loop so GetMessage was never called.

For example: put this code in any of the application types where you do see
WM_QUIT:

PostQuitMessage();
ExitProcess();

Clearly the behavior of PostQuitMessage hasn't changed, yet you'll never see
WM_QUIT returned by GetMessage.

[quoted text, click to view]

Re: Relationship between Application.Exit() and AppDomain Willy Denoyette [MVP]
4/8/2008 7:15:28 PM
[quoted text, click to view]


The docs are clear, but I'm afraid they are missing some additional remarks
when run on Vista (don't know what happens on XP SP2 and SP3).
Please don't point to the docs to prove I'm wrong, use some debugging tools
and correct me if you notice the *documented* behavior.
Running SpyXX [1] doesn't reveal any WM_QUIT message for a WPF enabled
application (say the sample posted by Barry), it does (as expected) when
called from any other type of application (managed Forms, and native MFC and
Win32).
If you can't get Spyxx (from VS2008) to work for you, or if you don't fully
trust what SPxx reveals(like I do), you can always run the app in the
debugger (say Windbg), set a breakpoint on GetMessageW and inspect the MSG
struct returned (there are quite a lot of them) when you call the API, you
won't see any WM_QUIT message (at least I don't).


Willy.

On Vista32 SP1 and Vista64 SP1 and WS2008, all running the same v3.5
Framework bits.
Re: Relationship between Application.Exit() and AppDomain Willy Denoyette [MVP]
4/9/2008 2:30:19 PM
[quoted text, click to view]
Hmmm, how do you expect see a WM_QUIT when you terminate the process
directly after PostQuitMessage ?


Also, I did break on PostQuitMessage (there are no A or W variants) don't
worry, your assumption that PQM has not changed may be valid for the "user"
portion, which is a small thunk [1] that calls into the kernel (syscall),
that's the place where messages are constructed, and that's where things got
changed dramatically in Vista, that's the portion that knows about "Avalon"
and the DWM. That's the portion that needs to coordinate with the DWM
composition, that's the part that handles PQM when called from a WPF
application running on Vista with DWM (glass) enabled.

[1]
0:000> uf user32!postquitmessage
USER32!PostQuitMessage:
00000000`76e90918 4863c9 movsxd rcx,ecx
00000000`76e9091b ba34000000 mov edx,34h
00000000`76e90920 e94bcc0000 jmp USER32!ZwUserCallOneParam
(00000000`76e9d570)

USER32!ZwUserCallOneParam:
00000000`76e9d570 4c8bd1 mov r10,rcx
00000000`76e9d573 b802100000 mov eax,1002h
00000000`76e9d578 0f05 syscall
00000000`76e9d57a c3 ret


Once again, the message loop is not terminated as a result of a WM_QUIT
message put in the message queue, none of the GetMessage calls return 0 once
PQM has been called, that means none of them have "picked-up" a WM_QUIT.
It's the DWM that stops the message loop, which doesn't mean that PQM is the
right API to call from WPF (it isn't).
You should start to convince yourself, I can't post more the debugger output
here. Start a kernel debugger session and look what PQM does in the kernel,
do the same thing when calling Application.Shutdow, look how thing got
coordinated with the DWM (using ALPC's ) over you will understand what I
mean here.
Don't be surprised when you got blocked by DRM in kernel debugger, don't be
surprised to see some COM interaction between the processes and don't be
surprised to find a some undocumented Windows messages in the application
queue.

Willy.

RE: Relationship between Application.Exit() and AppDomain Sunny S
4/10/2008 1:55:00 AM
Keep hitting wrong buttons, sorry...

Gentlemen, thank you very much for an interesting discussion, from which I
learned a lot, but I feel I had to be more specific.

1. Let’s say I’ve started a SimpleWinForm application. I presume that means
starting a message loop.

2. From within that application I create an AppDomain in which I create a
new thread on which I call Application.Run(new SomeOtherWinForm()). See, for
example, Jon Skeet’s code above except that the code should be running on a
dedicated thread in a separate AppDomain.

Microsoft documentation says that Application.Exit() method ‘Informs ALL
message pumps that they must terminate, and then closes all application
windows after the messages have been processed’.

From the above I would conclude that upon calling Application.Exit() both
SomeOtherWinForm and SimpleWinForm should close and the whole thing should
terminate. Experiments show that this is not the case – only SomeOtherWinForm
closes.

Again, Microsoft documentation for System.Windows.Application (not
System.Windows.Forms.Application!) says that there is only one instance of
Application object per AppDomain. It looks as if the same relationship is
true for System.Windows.Forms.Application objects and AppDomains, because
this would explain the above behaviour, but I wasn’t sure.

SS


[quoted text, click to view]
Re: Relationship between Application.Exit() and AppDomain Sunny S
4/10/2008 3:35:06 AM
Willy,

Thanks very much for a quick reply. Can you see any immediate problems I am
going to run into if I use Windows.Forms in multiple AppDomains?

SS


[quoted text, click to view]
Re: Relationship between Application.Exit() and AppDomain Sunny S
4/10/2008 10:45:00 AM
Hi Jon,

I modified your example code to create two threads and to start message
loops on each of them as follows:

static void Main()
{
{
Thread t = new Thread(ShowUI1);
t.SetApartmentState(ApartmentState.STA);
t.Start();

Thread t2 = new Thread(ShowUI2);
t2.SetApartmentState(ApartmentState.STA);
t2.Start();
}
}

static void ShowUI1()
{
Form form = new Form
{
Size = new Size(200, 200),
Text = "Form UI1"
};
Button b = new Button
{
Text = "Die!",
Location = new Point(5, 5)
};
b.Click += (s, e) => { Application.Exit(); };
form.Controls.Add(b);

Application.Run(form);
}

static void ShowUI2()
{

Form form = new Form
{
Size = new Size(200, 200),
Text = "Form UI2"
};
Button b = new Button
{
Text = "Die!",
Location = new Point(5, 5)
};
b.Click += (s, e) => { Application.Exit(); };
form.Controls.Add(b);

Application.Run(form);
}

If you run this code, you’ll see that when you kill one of the Forms the
other dies too and the application shuts down. Apparently, calling
Application.Exit() on one thread kills the other thread's UI as well. This is
in line with Microsoft documentation saying that Application.Exit() method
‘Informs all message pumps that they must terminate, and then closes all
application windows after the messages have been processed’.

Things seem to be different if you create these two threads in different
AppDomains like so:

public class Test: MarshalByRefObject
{
static void Main()
{
{
AppDomain ad1 = AppDomain.CreateDomain("AD1");
Test t1 = (Test)
ad1.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "Test");
t1.StartUI1();

AppDomain ad2 = AppDomain.CreateDomain("AD2");
Test t2 =
(Test)ad2.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName,
"Test");
t2.StartUI2();

}
}

public void StartUI1()
{
Thread t = new Thread(ShowUI1);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}

public void StartUI2()
{
Thread t = new Thread(ShowUI2);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}

public void ShowUI1()
{
Form form = new Form
{
Size = new Size(200, 200),
Text = "Form UI1"
};
Button b = new Button
{
Text = "Die!",
Location = new Point(5, 5)
};
b.Click += (s, e) => { Application.Exit(); };
form.Controls.Add(b);

Application.Run(form);
}

public void ShowUI2()
{

Form form = new Form
{
Size = new Size(200, 200),
Text = "Form UI2"
};
Button b = new Button
{
Text = "Die!",
Location = new Point(5, 5)
};
b.Click += (s, e) => { Application.Exit(); };
form.Controls.Add(b);

Application.Run(form);
}
}

In this case killing one of the Forms doesn’t kill the other one and this is
not in line with the documentation.

That’s, essentially, what my question was about.

Thanks for replying, it’s nice to hear from you again:)

SS

Re: Relationship between Application.Exit() and AppDomain Sunny S
4/10/2008 11:01:01 AM
Jon,

I’ve just done some more tests. My understanding of Willy Denoyette’s
explanation (see at the bottom of this thread) was that Application.Exit()
kills the message pumps in the current Appdomain and its ‘child’ AppDomains.

To verify this I further modified the code with AppDomains so that one of
the threads creates yet another ‘child’ AppDomain and starts yet another
message loop in it. This test showed that my understanding was incorrect. All
three message loops in those AppDomains are independent in the sense that
killing one of them doesn’t kill the others.
Re: Relationship between Application.Exit() and AppDomain Sunny S
4/10/2008 11:06:01 AM
Hi Willy,

Again, thanks for the reply. You might be interested in reading (and,
perhaps, commenting on:)) my reply to Jon Skeet above. I've done some
experiments to clarify dependecies between message pumps running in different
Re: Relationship between Application.Exit() and AppDomain Willy Denoyette [MVP]
4/10/2008 11:56:18 AM
[quoted text, click to view]

When the documentation says "all running message loops on all threads and
closes all windows of the application." it really should say in the callers
AppDomain (AD) and it's owning AD's.
That means, that if you call Application.Exit in a child AD , only the child
AD windows will be affected. If, however you cal A.E from the parent AD ,
then also the child AD windows will be affected.
Note also that Windows.Forms was not designed to be run from within multiple
domains in a single process.


Willy.



Re: Relationship between Application.Exit() and AppDomain Willy Denoyette [MVP]
4/10/2008 10:40:35 PM
[quoted text, click to view]



I know this is quite confusing, but I'm not sure why you consider this "not
inline with the docs".
Note that the docs talks about applications, and stopping all message pumps
in the application, it doesn't talk about threads running other AD's.

In your last sample you are creating separate AD/thread pairs *and* you
create a new application (Application.Run(..) in each of the
domains/threads, calling A.E in one of the AD/threads only stops the
(single) message pumps in this application, which is inline with the docs,
right?

Now, say the from AD1/thread1 you create another thread, and you create a
window and run a message pump in this thread. That means, you have
AD1/thread1 and thread2, and two separate message pumps. Calling A.E from
one of these threads will stop all (2) pumps, which is inline with the docs,
right?

And, say you have a AD/thread that runs an application
(Application.Run(...)], and this thread creates another AD that shows a
form. Here you have two AD's, one *Application* and only one thread that
pumps the message queue of both the main form and the other AD's form. When
you call A.E from the second form code, you will simply unload the second AD
and it's form, but you won't stop the message pump. Calling A.E from the
main form will stop the message pump and close all forms tear down the AD's
for the whole application, which is again inline with the doc's.

Willy.

Re: Relationship between Application.Exit() and AppDomain Sunny S
4/11/2008 12:52:00 AM
Hi Willi,

I agree that 'not in line with the docs' was, perhaps, an overstatement:).
What I actually wanted to say is that as far as I am concerned the
documentation was not clear about the scope of the Application object and the
relationship between Application, A.E method and AppDomains.

For example, you say ' ... you create a new application (Application.Run(..)
in each of the domains/threads ...' Define 'application'. Surely it's not a
new Application object or is it? BTW, the documentation just says that
calling A.R 'Begins running a standard application message loop on the
current thread'. I am not trying to be argumentative, I'm just trying to
understand what's going on.

Let's take one of your scenarios: "From AD1/thread1 you create another
thread, and you create a window and run a message pump in this thread." Why
can't I use the same logic as above and say that by 'creating a window and
running a message pump' on a new thread (through Application.Run(Form), I
presume) I create a new application?

Let's futher modify this scenario so that the second thread is created, as
above, from AD1/thread1, but in a separate AppDomain (AD2), so that AD2 is a
'child' of AD1. In this case, calling A.E on either of the threads doesn't
stop the other (I did test it:).

You see, this is the sort of questions I was trying to clarify for myself
and I found your comments quite helpful, thank you.

[quoted text, click to view]
Re: Relationship between Application.Exit() and AppDomain Sunny S
4/11/2008 4:45:02 AM
Hi Willi,

We are almost there:):):)

To recap, we have: AD1/T1 -> calls A.R(Form1); creates T2 -> creates AD2 ->
call A.R(Form2). Here calling A.E on T2 does close Form2, but doesn't close
Form1. The reverse is also true: calling A.E on T1 closes Form1, but doesn't
close Form2.

I accept your explanation that A.R(Form2) creates a new 'application' that
is independent of the application running Form1, so exiting one of them
doesn't affect the other.

Why then things are different for the following scenario: AD1/T1 -> calls
A.R(Form1); creates T2 -> calls A.R(Form2), where we don't create a separate
AppDomain for T2? As you pointed out erlier, closing either Form1 or Form2
closes the other Form and shuts down the application.

Apparently, calling A.R on a different thread in a separate AppDomain is
somehow different from calling it in the same AppDomain. Would it be correct
to assume that the scope of Application.Exit() is limited to the current
AppDomain only?


[quoted text, click to view]
Re: Relationship between Application.Exit() and AppDomain Sunny S
4/11/2008 9:18:00 AM
Hi Willy,

Well, what can I say? A big thank you, again:)

As for your question why am I so interested in A.E -- at this point it's
already, perhaps, a bit of an obsession. My original interest was triggered
by attempts to find a way to rudely shut down an application that is running
in an AppDomain that was created by a host. The app is supposed to be written
by a third party, should be considered as an untrusted one and peppered with
bugs (that is, in addition to our own bugs:)). If that app enters a tight
loop, then I couldn’t see a way to quit it gracefully other than calling A.E.
Unloading an AppDomain, even if that was possible with a foreground thread
still running in it, wouldn’t be a good option since we would loose state
information. So A.E seemed to be a reasonable option. So I started thinking
of what would happen if I inject a thread into that problematic AppDomain and
call A.E on it, and then I came up with some other scenarios most of which
included A.E in one way or another. Obviously, I needed to understand what
are possible ramifications, etc. BTW, where and how can I learn what happens
‘under the hood’? I tried Reflector, but the most interesting (and messy?)
parts of functionality are hidden in internal methods which Reflector
wouldn’t ‘reflect’:)). I don't want to be too intrusive, but how did you
learn what's going on behind 'the big picture'?

Regards,

SS
Re: Relationship between Application.Exit() and AppDomain Willy Denoyette [MVP]
4/11/2008 1:03:18 PM
See inline.


WIlly.

[quoted text, click to view]
Well, as said before, Windows.Forms was designed to be used from the
"default domain" only and not from muttiple AD's running in the same
process. The reason is quite simple, the underlying Win32 Windows
architecture doesn't know about AD's, it only knows about processes and
threads and one thread which is important in the "Windows" context is the UI
thread. It's the thread that must run a message pump in order to retrieve
Window messages from the application and from the System.


[quoted text, click to view]

A.R creates an ApplicationContext (and a static Application instance ), it's
the ApplicationContext who actually defines *the* application in terms of
the MSDN docs.


[quoted text, click to view]

You create a new Application in terms of the docs, that's right.

[quoted text, click to view]
Ok so you have:
AD1/T1 -> creates T2 -> creates AD2 -> call A.R which creates a new
ApplicationContext (a new application as per msdn) which start a pump on T2.
Calling A.E in T2 will stop the pump on T2, destroy the ApplicationContext
and as such stop this application.
The fact that you do this is a new AD is irrelevant, an AD != an
"application".



[quoted text, click to view]

Re: Relationship between Application.Exit() and AppDomain Willy Denoyette [MVP]
4/11/2008 4:50:31 PM
[quoted text, click to view]

Yep.

[quoted text, click to view]
Here you create one AD, 2 threads, 2 applications (ApplicationContexts,
ApplicationThreadContexts, etc... ) , 2 message pumps (one per thread).
When you call A.E in one of the threads, you get rid of all of the
ApllicationContexts in the containing AD and it's AD children.
Note that what's happening is quite more complex, but that's the big
picture.

Why are you so interested in A.E's behavior, which is not the most
appropriate way to stop an application anyway, just currious.


[quoted text, click to view]
Re: Relationship between Application.Exit() and AppDomain Sunny S
4/12/2008 7:01:01 AM
Hi Jeff,

Thanks for replying and for your comments. To answer your questions,

1. Yes, the app we are writing is being coded in Winform, it's not a Web
application, at least for the time being.

2. I can see two explanations for our design being strange to you:) - a) we
are doing something genuinely stupid; b) we are doing something genuinely new
(a combination of both is also an option:):):)). On a serious note, we are
trying to create an app that would host some other applications, either GUI
or non-GUI, which would be configurable through the host UI. The host is
supposed to be non-intrusive; once the apps are configured they should run as
there is no host, although they would be required to respond to host’s
request about their status.

3. Why don’t I call AppDomain.Unload()? I actually do, but there are
scenarios when I don’t want or cannot do this. (a) If the 3rd party app that
sits in this AppDomain is running a foreground thread then AppDomain.Unload
throws an exception. (b) If there is a problem with a 3rd party app, so that
it cannot continue, we would like to stop it - not in a graceful way, perhaps
- and grab some status data. Then we can unload the whole thing. (c) We
should be able to stop the 3rd party app, reconfigure it and start again.

4. Just to illustrate what I was talking about when I said that there were
limits to which Reflector could ‘reflect’, let’s take the Object class. Look,
for example, at

internal static extern bool InternalEquals(object objA, object objB)

As far as I know, there is no matching Win32 API to p/invoke and this is as
far as I can go in exploring the CLR internals.

Anyway, thank you very much for your help.

SS

[quoted text, click to view]
Re: Relationship between Application.Exit() and AppDomain Jeffrey Tan[MSFT]
4/12/2008 4:26:59 PM
Hi Sunny,

Sorry for the late response to you, I am out of office yesterday. Anyway, I
am glad Willy has provided a great and informative discussion with you.

I assume your application is coded in Winform since you are using
System.Winforms.Forms.Application. So, your application created a seperate
AppDomain to host the 3rd party code for security/robustness reason ? Can
you tell us if the 3rd party code is also GUI code? This design and
achitecture looks strange to me, since I did not see any programs using this
design. We normally run the semi-trusted non-GUI addin in the separate
AppDomain.

I ask these because Application.Exit can only be used in GUI Winform code
not normal non-GUI code. Also, it can only shut down the GUI threads in the
*Application*. If the 3rd party code created a few more worker(non-GUI)
threads, they will be cleaned by Application.Exit. As Willy originally
pointed out, Application.Exit() has nothing to do with AppDomain, so it will
not help to clearn AppDomain. Why don't you call AppDomain.Unload method to
get rid of the buggy 3rd party code?

Regarding your last question, I think Reflector should be the best tool to
understand the .Net BCL internal work. What internal call functions do you
have problem to understand? As I know Winform purely encapsulates the Win32
GUI code, so I assume most of the non-.Net code is p/invoking the Win32
User32 APIs. The Win32 GUI programming books(such as <Programming Windows>)
should be good resource to help you understand GUI APIs.

Hope this helps.

Best regards,
Jeffrey Tan
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:
msdnmg@microsoft.com.

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

Re: Relationship between Application.Exit() and AppDomain Sunny S
4/14/2008 5:27:01 AM
Hi Jeff,

Thanks for replying and my special thanks for the link to FCall. This should
be very useful (or at least very interesting:) ).

Regarding (a) in my previous post: The exception that AppDomain throws is
actually CannotUnloadAppDomainException and VS2008 gives a hint: 'Make sure
you are not trying to unload an application domain that ... has a running
thread ...'. Again, this is only a problem for foreground threads.

Regarding (b): basically the idea is to stop all processing, create some
types defined in the loaded assemblies, and call some methods on those types.
It may not be always possible if one of the types is running a tight loop on
a foreground thread. So the first thing to do is to try and kill all the
threads.

Regarding (c): The host we are writing should be able to swap an assembly
that is suspected to cause problems with an alternative one. Of course, this
is also possible by unloading the AppDomain and loading it with the same
assemblies except the suspected one. However, in our case under certain
scenarios this could be time consuming and as an alternative we are
investigating the possibility of swapping only the suspected assembly
without unloading the whole set.

Books recommendations: I've already read Jeff Richter’s <CLR via C#> (both
editions) and right now I am finishing <Customizing The Microsoft .Net
Framework CLR> by Steve Pratschner. <Shared Source .. > seems to be
interesting, thanks, I’ll have a look.

Again, thank you very much for your help. Where do you guys find time to
answer all our questions?:) You seem to be so willing to help; that’s quite
impressive..

Regards,

SS


[quoted text, click to view]
Re: Relationship between Application.Exit() and AppDomain jetan@online.microsoft.com (
4/14/2008 9:17:43 AM
Hi Sunny,

Thanks for your feedback.

Regarding "(a) If the 3rd party app that sits in this AppDomain is running
a foreground thread then AppDomain.Unload throws an exception", do you mean
ThreadAbortException thrown in the thread in the 3rd party AppDomain? Yes,
AppDomain.Unload() method uses Thread.Abort() method on the target thread
to terminate the threads. ThreadAbortException will perform stack unwind on
the target stack to perform clean-up and then terminate the target thread.
Then, what is the problem of this behavior?

Regarding (b) and (c), I also do not think I understand the key points.
What is the problem of AppDomain.Unload() against your (b) and (c)
requirement?

Regarding the Reflector issue, it seems that you are interested in the
internal routines implemented by the CLR. Yes, a lot of .Net services are
implemented in the CLR via native code. They are using "FCall" into the CLR
which can not be examined using Reflector. The only way to examine its
implementation is reversing engineer(disassemble) it. Also, Microsoft
released an open-source CLR implementation called SSCLI, which contains an
example implementation of CLR and .Net Framework. You may examine its
source code to understand these FCall functions. The SSCLI source code is
not guaranteed to be the same as CLR, but most of the principles are the
same. The articles below also talks about FCall:
http://blogs.msdn.com/yunjin/archive/2004/02/08/69906.aspx
https://blogs.msdn.com/joelpob/archive/2003/12/18/53745.aspx

Also, a lot of interesting books talk about CLR internal implementation,
such as Jeffrey Richter's <CLR via C#>, Don Box's <Essential .Net>, <Shared
Source CLI Essentials> etc.. They are helpful to understand CLR principles.

Hope this helps.

Best regards,
Jeffrey Tan
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:
msdnmg@microsoft.com.

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


Re: Relationship between Application.Exit() and AppDomain Sunny S
4/15/2008 2:43:00 AM
Hi Jeff,

Thanks for replying. To answer your question whether I tried to find out why
Thread.Abort() didn’t terminate the foreground thread, - no, I didn’t even
try. First, I am lazy and I prefer to ask experts; this does save time in the
short run:) Second, the documentation on Thread.Abort says ‘The thread is not
guaranteed to abort immediately, or at all’ and that is enough for me (see
the first reason:))).

In my simplistic scenario the thread was doing something like this: while
(true) {}; so given the information I found at

http://www.ondotnet.com/pub/a/dotnet/2003/02/18/threadabort.html

I assumed there was no chance for that sort of thread to be aborted. Then I
asked myself a question why is it still aborted when it is created as a
background thread? I figured that trying to find an answer to this question
would take me an unjustified amount of time given the fact that stopping the
thread by Application.Exit() gives an immediate practical solution. I do need
to read the books you’ve recommended …

Regards,
SS


[quoted text, click to view]
Re: Relationship between Application.Exit() and AppDomain jetan@online.microsoft.com (
4/15/2008 8:12:44 AM
Hi Sunny,

Thank you for explaining it in details.

Oh, I was not aware of that the foreground UI thread will block the
AppDomain.Unload() method with CannotUnloadAppDomainException. Have you
invested to find out why the Thread.Abort did not terminate the target
thread? I have had a hard time to understand why the thread did not
terminate.

Anyway, if Application.Exit() can terminate all the foreground GUI threads
in the target AppDomain, I think we can call Application.Exit() to
terminate all the UI threads in the target AppDomain and followed with an
AppDomain.Unload() method calling to clean up the target AppDomain.

<Shared Source CLI Essentials> explains the CLI(which is very similiar with
CLR) in source-code level, so it has a deeper insight than other CLR books.
<Customizing The Microsoft .Net Framework CLR> targets the CLR hosting
topics in depth.

Actually, I am the .Net CLR and VS.net debugging newsgroups MSDN
subscription support engineer, so it's my job and pleasure to help you
:-).(Also, I learned a lot in the newsgroup discussion)

Best regards,
Jeffrey Tan
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:
msdnmg@microsoft.com.

This posting is provided "AS IS" with no warranties, and confers no rights.
Re: Relationship between Application.Exit() and AppDomain Willy Denoyette [MVP]
4/15/2008 10:28:33 AM
[quoted text, click to view]