Thursday, June 10, 2010

Error: ShowDialog exits immediately

I was trying to implement a WinForm login class called from a menu navigation class, but when I called ShowDialog(), it was exiting immediately without displaying the window or setting the DialogResult code. It was working the first time through the loop, but subsequent calls always failed. I searched all over the 'net for answers without success; in the end, I had to trace through my program a few lines at a time in the debugger until I found the culprit.

Watching the behavior of the preparation call to Login.ShowDialog() resulted in everything appearing normal the first time. Later, the Owner property would not allow assignment - no error, but the value stayed null - and calling ShowDialog() would return immediately with the default value of DialogResult.None. My Load event was even being called as expected. To me, this appeared to be working incorrectly. It turned out to be not incorrect, but undefined behavior I was seeing.

As the stereotypical engineer, I nearly outsmarted myself by designing a library of classes that would handle the details of performing their appropriate menu operations and allow me to define the menus declaratively. One of the classes was responsible for calling a named method and instantiating its type object through reflection if needed. To allow a ShowDialog() method call, the .NET Framework requires the object to be manually disposed afterward. I got fancy and added code to call Dispose() on the object automatically if it was a Form. But...some of my called methods were part of my active menu navigation class, which was itself a Form. When the menu operation was executed, my navigation class got destroyed, so I was clobbering myself.

The resolution was to be careful to not dispose of the class I was actively using. Assigning a disposed Form as the owner of another Form is undefined, pointless, and creates bizarre results, as I so painfully found. Fixing this issue solved the inconsistent behavior. I'm deservedly embarrassed by my mistake, but wiser for it.

If this saves somebody else the inconvenience I experienced to track down this problem, then it will have been worth my time to share this story. Leave me a comment if this helped you in any way.