Exception when displaying a modal dialog

A

Alain Dekker

Hi,

Using VS 2005, C# targetting CF .NET v2.0 on Windows CE.

Really confused with this one. I have a modal dialog which I display on a
form. The dialog asks me to perform certain tasks (its an application in a
factory, the tasks in this case are to pass packs along a conveyor, there is
an electrical signal generated by a photoeye in front of a piece of
equipment, then another signal from another photoeye after the equipment).
The tasks are complete when all packs requested have passed the first
photoeye. Once all tasks are complete, I display a message on the bottom,
"All done!" and then a timer ticks and about 2s later, I close the form.

Fine, works well.

Occasionally, a mistake is made in the task. For example, the pack passes
the first photoeye but then falls off the conveyor. In this case, I pop up
another modal dialog to show an error. If I display this while there are
still tasks to complete (the operator needs to pass 5 packs, and we're on
pack 3), then simply ok the fault message, complete the rest of the tasks,
and everything works fine.

But, if I show this fault dialog after all five packs have passed the first
photoeye, when I display my "All done!" message and close the earlier modal
dialog, I get an exception. Cannot understand why. Exception stack is as
follows:

System.ArgumentException was unhandled
Message="Value does not fall within the expected range."
StackTrace:
at Microsoft.AGL.Common.MISC.HandleAr()
at System.Windows.Forms.Form._CloseModal()
at System.Windows.Forms.Form.Close()
at IQ3_GUI.frmMain_PVS.tmrPVTest_Tick()
at System.Windows.Forms.Timer._WnProc()
at
System.Windows.Forms.ApplicationThreadContext._InternalContextMessages()
at Microsoft.AGL.Forms.EVL.EnterModalDialog()
at System.Windows.Forms.Form.ShowDialog()
at IQ3_GUI.frmMain.SetCurrentProductValues()
at IQ3_GUI.frmMain.tmrDisplay_Tick()
at System.Windows.Forms.Timer._WnProc()
at
System.Windows.Forms.ApplicationThreadContext._InternalContextMessages()
at Microsoft.AGL.Forms.EVL.EnterModalDialog()
at System.Windows.Forms.Form.ShowDialog()
at IQ3_GUI.frmMain.RunPVSTest()
at IQ3_GUI.frmMain.btnPVS_Click()
at System.Windows.Forms.Control.OnClick()
at System.Windows.Forms.Control.WnProc()
at System.Windows.Forms.Control._InternalWnProc()
at Microsoft.AGL.Forms.EVL.EnterModalDialog()
at System.Windows.Forms.Form.ShowDialog()
at IQ3_GUI.frmCommon.Start_IQ()
at IQ3_GUI.frmCommon.tmrLoad_Tick()
at System.Windows.Forms.Timer._WnProc()
at
System.Windows.Forms.ApplicationThreadContext._InternalContextMessages()
at Microsoft.AGL.Forms.EVL.EnterMainLoop()
at System.Windows.Forms.Application.Run()
at IQ3_GUI.Program.Main()

Any ideas? Thanks in advance,
Alain
 
A

Alain Dekker

Thanks for the suggestion, Peter. Following your advice, I've set a flag
from the main form, accessible from the first modal form, when the second
modal form is displayed. The flag is cleared when the second modal form is
closed (by user action).

When the first modal form closes, I check this flag. If it is not set (the
second modal form has not been displayed), I just close the first modal form
as normal. If the flag is set (the second modal form has been launched),
instead of closing the form, I start a timer that spins around, constantly
checking when the flag is cleared. When the flag does clear, I wait a few ms
and then close the form.

So far, I was consistently able to reproduce the exception and app crash
before, and with the new method, I cannot reproduce it. I have to agree the
user experience is better.

Thanks!

I've tried to reproduce the problem on Windows XP using an app written in VS
2003.NET and targetting .NET 1.1. Works fine. Although the first form has
closed, it doesn't actually disappear until the second form goes away. And,
no crash, no exception. I then tried the same thing in VS 2005, targetting
..NET 2.0 and same result, no crash. Haven't had time to try it on Windows CE
yet (apart from my large app which does show the problem).

I'm thinking this is a bug in Windows CE or the Compact Framework .NET v2.0.
In any case, closing the first modal form when a second has been launched
isn't erribly good design anyway, so I've no problem fixing the bug as
suggested.

Regards,
Alain


Peter Duniho said:
[...]
Occasionally, a mistake is made in the task. For example, the pack passes
the first photoeye but then falls off the conveyor. In this case, I pop
up
another modal dialog to show an error. If I display this while there are
still tasks to complete (the operator needs to pass 5 packs, and we're on
pack 3), then simply ok the fault message, complete the rest of the
tasks,
and everything works fine.

But, if I show this fault dialog after all five packs have passed the
first
photoeye, when I display my "All done!" message and close the earlier
modal
dialog, I get an exception. Cannot understand why. Exception stack is as
follows: [...]

Hard to say without a proper concise-but-complete code example that
reliably reproduces the problem.

One possibility is that when you've displayed the second modal dialog, you
passed the first modal dialog as the parent. Then when you try to close
the first model dialog while the second is still visible, Windows
complains.

Another possibility is that Windows notices that the window proc for the
first modal dialog hasn't returned yet from handling the "tmrDisplay_Tick"
event and complains that you are trying to close a window that is still
waiting to finish processing a message.

In any case, I would suggest that regardless of whatever rule in .NET or
Windows your code is breaking, it's pretty weird from a user-experience
point of view for a dialog under the top-most modal dialog to just
disappear before the top-most one has been dispensed with. Perhaps a
better design for the user, and one which would avoid tricky re-entrancy
or object-relationship issues, would be for the closing of the first modal
dialog to be deferred until after the second modal dialog has been closed,
if that second modal dialog is being displayed.

Pete
 
A

Alain Dekker

Good point about the "few ms" delay, thanks. BTW, how does Form2 subscribe
to the FormClosed event on Form3? I know how to act on the event in Form3
itself, but not from another class.

Thanks,
Alain

Peter Duniho said:
Thanks for the suggestion, Peter. Following your advice, I've set a flag
from the main form, accessible from the first modal form, when the second
modal form is displayed. The flag is cleared when the second modal form
is
closed (by user action).

When the first modal form closes, I check this flag. If it is not set
(the
second modal form has not been displayed), I just close the first modal
form
as normal. If the flag is set (the second modal form has been launched),
instead of closing the form, I start a timer that spins around,
constantly
checking when the flag is cleared. When the flag does clear, I wait a few
ms
and then close the form.

So far, I was consistently able to reproduce the exception and app crash
before, and with the new method, I cannot reproduce it. I have to agree
the
user experience is better.

Thanks! [...]

Glad the suggestion helped. For what it's worth, in terms of
implementation, I would have approached it slightly differently. In
particular, rather than polling to see whether the second dialog has been
closed, just subscribe to that form's FormClosed event and then close the
first form as needed when the event is raised.

Similarly, you should not need to "wait a few ms" for anything. All the
GUI code is executing in the same thread, so all that waiting a few ms
does is delay your whole program by a few ms. The exact sequence of
instructions executed will otherwise be the same and since no user can
detect a delay that's only a few ms long, such a delay has no material
beneficial effect on the program.

Pete
 
A

Alain Dekker

Aah, cool, I hadn't seen that technique before. So the parent form gets a
chance to do something before the child has actually closed! Nice...

Thanks,
Alain
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top