What is the origin of this set_Visible exception during shutdown of winforms application?
I have wrapped the Application.Run method in try/catch
[STAThread]
private static void Main(string[] args)
{
try {
MyClient client = new MyClient();
client.Run(args);
}
catch (Exception ex) { log.Error("Failed to start client",ex); }
}
Where MyClient is just:
class MyClient : WindowsFormsApplicationBase
and during every shutdown I get this exception
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'MainView'.
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.Form.CreateHandle()
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Control.SetVisibleCore(Boolean value)
at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
at System.Windows.Forms.Control.set_Visible(Boolean value)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at MyProgram.Main(String[] args) in C:\svn\trunk\MyProg开发者_C百科ram\client\MyProgram\Program.cs:line 54
If I set a breakpoint in the debugger in the catch block my callstack is all empty except for the client.Run(..)
.
As far as I can understand the stacktrace the problem is somewhere some code is doing MainView.Visible = ....
but I can find anything in my code that resembles this.
How can I figure out the origin of the exception?
The MainView is created like this inside MyClient
:
protected override void OnCreateMainForm()
{
string[] args = Environment.GetCommandLineArgs();
try {
MainView mainView = new MainView(args);
this.MainForm = mainView;
Application.EnableVisualStyles();
Application.Run(mainView);
}catch(Exception ex){ log.Warn("Exception in OnCreateMainForm",ex); }
}
And closing like this:
public void OnKilled()
{
log.Debug("OnKilled. Exiting");
Application.Exit();
}
MainView
is defined like:
public partial class MainView : Form
{
private void InitializeComponent()
{
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainView_FormClosing);
}
private void MainView_FormClosing(object sender, FormClosingEventArgs e)
{
log.DebugFormat("'MainView_FormClosing': {0}",e.CloseReason);
if (e.CloseReason == CloseReason.WindowsShutDown || e.CloseReason == CloseReason.ApplicationExitCall)
{
e.Cancel = false;
Application.Exit();
}
}
Can you please post the code that you use in order to create the main window, and the code that you use in order to close it?
Without seeing more code, I would guess that somewhere in your code you are calling Dispose
on the windows, instead of using Close
. But that's just a guess.
By the way, why are you using WindowsFormsApplicationBase
if this is a C# program?
Aha!
It turns out that Application.Run
in OnCreateMainForm is the big No-No. WindowsFormsApplicationBase
takes over the ApplicationRun when OnCreateMainForm
returns so in my case I only returned from OnCreateMainForm
when MainForm already were disposed hence the exception :(
protected override void OnCreateMainForm()
{
string[] args = Environment.GetCommandLineArgs();
try {
MainView mainView = new MainView(args);
this.MainForm = mainView;
Application.EnableVisualStyles();
}...
}
精彩评论