I am developing a .NET 2.0 plug-in based application. My application detects/loads plug-ins at run-time via a System.Reflection inspection of other .NET assemblies in a specified directory. This works great. My application contains a PropertyGrid control populated from [Browsable(true)] properties present in the loaded plug-ins. In this PropertyGrid, browsable-true-properties exhibit the following behavior:
- Properties of basic/primitive types (bool, string, etc.) load and cleanup properly
- Properties of user-defined types (like a plug-in side defined enum) load properly and cleanup properly when the user does not modify then at run-time.
- If a user modifies a non-standard type at run-time (i.e. changes the value of an enum via the PropertyGrid) the application hangs upon closing. This is my problem.
Using Visual Studio .NET 2005 and Red Gate's Reflector, I was able to isolate the hang to the following segment of code from Microsoft.Win32.SystemEvents.WindowThreadProc (I was working from the raw assembly, but I am 99% sure this is the right place):
while (flag)
{
if (UnsafeNativeMethods.MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 100, 0xff, 4) != 0x102)
开发者_运维技巧 {
goto Label_0072;
}
Thread.Sleep(1);
continue;
Label_0053:
if (msg.message == 0x12)
{
flag = false;
continue;
}
UnsafeNativeMethods.TranslateMessage(ref msg);
UnsafeNativeMethods.DispatchMessage(ref msg);
Label_0072:
if (UnsafeNativeMethods.PeekMessage(ref msg, NativeMethods.NullHandleRef, 0, 0, 1))
{
goto Label_0053;
}
}
It appears 'flag' is not being set to true, hence my program sits in this loop forever. I found someone with a similar problem at .NET 247, but his recommended workaround:
System.Threading.Thread.CurrentThread.SetApartmentState(Threading.ApartmentState.STA)
didn't seem to fix things.
Any thoughts?
Thanks in advance.
Make sure your entry point for your application is flagged [STAThread]
- the STAThreadAttribute is the only way in .NET 2+ to mark your UI thread as STA. Setting the ApartmentState after the thread's started (which worked in 1.1) is not valid guidance anymore.
This should look like:
public class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MyMainForm());
}
}
Lookst like you've isolated the problem incorrectly. The code that you've posted is for a window procedure for an invisible window used by WinForms to catch system window messages (like WM_SETTINGCHANGE). It's run on a thread different from your main thread, so it shouldn't affect it in any way. If you have just attached the debugger to your process, most likely you've got the wrong thread.
The flag here is actually set when window gets WM_QUIT. However, this shouldn't matter, because the thread is also created as a background thread, meaning that it will be killed anyway when your main thread terminates - so even if the flag isn't set and it keeps looping, it still won't hang the app on exit.
(all of the above is easy to find out if you look at .NET source code available from MS debugging source servers if you use VS2008 SP1).
For the reference of anyone who stumbles across this in the future:
Friend Class Starter
<STAThread()> _
Shared Sub Main()
Application.EnableVisualStyles()
Dim client As ClientGUI
client = New ClientGUI()
Application.Run(client)
My.Settings.Save()
End Sub
End Class
精彩评论