Technical Journal

Programming, software technologies, operating systems, IT

.NET NumericUpDown crash workaround

I encountered the following problem when trying to handle a NumericUpDown_ValueChanged event :

In the event handler, the code was very similar to this template :

if( someVal > numericUpDown.Minimum && someVal < numericUpDown.Maximum )

{

// do something here

}

else

{

MessageBox.Show( “Some message” );

}

When the user holds the mouse pressed on one of the control arrows and the MessageBox is to be shown, I get an exception that is more than unexpected.

Here is the complete stack trace :

System.Transactions Critical: 0 : <TraceRecord xmlns=”http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord”
Severity=”Critical”>
<TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier>
<Description>Unhandled exception</Description>
<AppDomain>YOUR_PROJECT_NAME.vshost.exe</AppDomain><Exception>
<ExceptionType>System.NullReferenceException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>Object reference not set to an instance of an object.</Message>
<StackTrace> at System.Windows.Forms.UpDownBase.UpDownButtons.TimerHandler(Object source, EventArgs args)

at System.Windows.Forms.Timer.OnTick(EventArgs e)
at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at

… your line of code …

at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()</StackTrace><ExceptionString>System.NullReferenceException: Object reference not set to an instance of an object.
at System.Windows.Forms.UpDownBase.UpDownButtons.TimerHandler(Object source, EventArgs args)
at System.Windows.Forms.Timer.OnTick(EventArgs e)
at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at

… your line of code …

at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()</ExceptionString></Exception></TraceRecord>
A first chance exception of type ‘System.Threading.ThreadAbortException’ occurred in mscorlib.dll

As I was to find out digging some Microsoft forums, this is a known, documented issue of the
Microsoft .NET framework. ( https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=251486&wa=wsignin1.0 ).

The workaround is available on this forum and it was of real help to me :

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1554539&SiteID=1.

Basically, “the control does not expect to get a message while it is executing an event handler. The workaround delays your response and lets the control finish its event handling. “

This is a sample( skeleton ) of my code, that uses a delegate instead of the MethodInvoker on the Microsoft forum example :

private delegate void CallMethodParam2( double x, bool y );

private void NumericUpDown_ValueChanged(object sender, EventArgs e)
{

if ( (someVal >= numericUpDown.Minimum ) && ( someVal <= numericUpDown.Maximum ) )
{

// some code

}
else
{

// Cancel changes
this.ShowError( someVal );

}

}

private void ShowError( double someVal )
{

bool bLess = true;

double val = 0;

if ( someVal<= numericUpDown.Minimum )
{

bLess = true;

val = numericUpDown.Minimum ;

}
else if ( someVal >= numericUpDown.Maximum)
{

bLess = false;

val = numericUpDown.Maximum;

}
this.BeginInvoke( new CallMethodParam2( this.ShowError ), new object[ ] { val, bLess } );

}
private void ShowError( double dist, bool bLess )
{

string text = “Distance “+ ( ( bLess ) ? “less” : “greater” ) + ” than ” + dist.ToString( ) +” not allowed!”;

MessageBox.Show( text, “Error”, MessageBoxButtons.OK, MessageBoxIcon.Error );

}

July 30, 2007 Posted by andocs | Windows | | No Comments Yet

Canceling the Load Form event in .NET

I was trying to find a way not to load a form when some error condition occured.

Briefly, the whole cancel logic should be placed in the constructor of the form and an exception should be thrown whenever canceling is necessary. The Show or ShowDialog methods must be included in the same try-catch block as the constructor.

Thus, when the exception is thrown, no form is displayed. There is no reliable way of canceling the Load event from within the Load event handler : if you call Close( ), you get an exception of the type : “Cannot acces a disposed object” on the Show or ShowDialog form methods.

See the following discussion also :

http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=1286.

July 20, 2007 Posted by andocs | Programming, Windows | | No Comments Yet