locked
NativeWindow.Callback() excpetion RRS feed

  • Question

  • For months I've been plagued by a mysterious bug. The bug is very rare and
    seems to only appear when running the application outside of the debugger.
    In addition, the bug will only appear for a typical user a few times per
    month, so its rarity makes it even harder to track down.

    The app is coded in Visual Studio 2005.

    When the bug strikes, a standard "Unhandled exception has occurred in your
    application" dialog appears with this trace:

    System.Threading.ThreadAbortException: Thread was being aborted.
    at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
    at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.Callback(...)

    Does anyone know what could cause an exception with a stack trace like this?
    The stack trace implies that a Timer is involved, but I've double-checked
    all the Timers and I can't see how this would be the case.

    I'd love it if I could understand what could cause this bug, but if that's
    not possible, as a consolation prize I'd at least like to suppress the
    unhandled exception dialog from appearing. I'm already handling these
    events...

    Application.ThreadException += new
    System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

    AppDomain.CurrentDomain.UnhandledException += new
    UnhandledExceptionEventHandler(WorkerThreadHandler);

    ....but this unhandled exception message is still getting through.

    By decompiling the .Net DLLs I can see that DefWndProc() has the following
    definition:

    public void DefWndProc(ref Message m)
    {
    if (this.previousWindow == null)
    {
    if (this.defWindowProc == IntPtr.Zero)
    {
    m.Result = UnsafeNativeMethods.DefWindowProc(m.HWnd, m.Msg,
    m.WParam, m.LParam);
    }
    else
    {
    m.Result =
    UnsafeNativeMethods.CallWindowProc(this.defWindowProc, m.HWnd, m.Msg,
    m.WParam, m.LParam);
    }
    }
    else
    {
    m.Result = this.previousWindow.Callback(m.HWnd, m.Msg, m.WParam,
    m.LParam);
    }
    }


    Can someone shed some light on what my app might be doing to cause a
    ThreadAbortException to be thrown in this method?

    Sunday, September 21, 2008 9:31 PM

Answers

  •  
    private System.Diagnostics.Stopwatch stopWatch1;  
    //*****  
     
    private void fillDiariesTable ( )  
            {  
                this.stopWatch1 = new Stopwatch ( );  
                this.stopWatch1.Start ( );  
                while ( true )  
                {  
                    if ( this.stopWatch1.ElapsedMilliseconds >= 500 )  
                    {  
                        this.stopWatch1.Stop ( );  
                        break;  
                    }  
                }  
                Auxiliaries axil = new Auxiliaries ( );  
                if ( Globals.diariesTable == null )  
                {  
                    axil.createDiariesTable ( "diaries" );  
                } 
    I think I use it here to create an artificial delay because the next process encroaches onto the previous one.
    AlexB
    Monday, September 22, 2008 9:34 PM
  •  I believe you are still missing a point. I don't want to put the thread to sleep. I want it to continue doing what it is doing. This thing works for me exactly as I expected. The other piece of code is being executed and this one is put on the grind to wait.

    You can easily use StopWatch to run periodic processes as I said. Once your assigned time is over, restart the stopwatch again.

    AlexB
    Tuesday, September 23, 2008 7:35 PM

All replies

  •  I posted your DefWndProc to my code and looked at it. I doubt the cause is there. The word "timers" however stuck fear in my heart. They are very nasty animals. In my experience they are such troublemakers that I am now avoiding using them altogether.

    I suggest you review your code and whenever possible replace them with StopWatch Class. That thing seems to be working flawlessly.

    Pay attention to what intervals your timers are measuring. If they are too small that event can be easily skipped. If they are in separate threads from the code they are supposed to influence, it is another source of trouble.

    AlexB
    Sunday, September 21, 2008 11:02 PM
  • Thanks for your reply!  You may be thinking of a different kind of timer.  I don't use any timers to measure elapsed time.  The only timers in my code are those things you use if you want Windows to periodically call a method.
    Sunday, September 21, 2008 11:27 PM
  •  Still use StopWatch for that.
    AlexB
    Monday, September 22, 2008 12:38 AM
  • I'm not sure how I can use StopWatch to periodically perform an action.  With Timer I can subscribe to its Tick event and it will call the method I supply, say, once every two seconds.  I couldn't find any functionality in StopWatch that would allow me to run a method at regular intervals.
    Monday, September 22, 2008 2:27 AM
  • The more I look into this the stranger it gets.  By decompiling more of the .NET code I saw that TimerNativeWindow overrides NativeWindow.OnThreadException() so that it calls Application.OnThreadException(e).  This means that I should be able to use the Application.ThreadException event to handle this problem.  To test it, I purposely aborted the current thread from within Timer's Tick event handler, and discovered that Application.ThreadException was in fact called with an Exception, as long as the app was run outside of VS.  This was the trace:


    EXCEPTION System.Threading.ThreadAbortException: Thread was being aborted.
       at System.Threading.Thread.AbortInternal()
       at System.Threading.Thread.Abort()
       at timer_Tick(Object sender, EventArgs e) in C:\Project\MainForm.cs:line 4307
       at System.Windows.Forms.Timer.OnTick(EventArgs e)
       at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

    However, the bug my users occasionally experience does not go through my Application.ThreadException handling, even though the bottom two lines of the trace are the same.  By looking at the .NET library code, this appears to be impossible.  Could it be a bug in .NET?

    • Edited by Fastrak Monday, September 22, 2008 2:41 AM
    Monday, September 22, 2008 2:39 AM
  •  You ca easily use StopWatch to run periodic events. Just restart it anew every time it stopped.
    AlexB
    Monday, September 22, 2008 2:19 PM
  • Maybe I'm looking at the wrong class?  This is the only stopwatch that I found when searching in Google: http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch_members.aspx

    I can't find any event to subscribe to that will tell me when the watch has stopped.  If that is the class you were referring to, could you please give me a code snippet on how to use it to run a period event?  I can't figure out how.

    Thank you very much for all your replies so far!

    Monday, September 22, 2008 8:10 PM
  •  
    private System.Diagnostics.Stopwatch stopWatch1;  
    //*****  
     
    private void fillDiariesTable ( )  
            {  
                this.stopWatch1 = new Stopwatch ( );  
                this.stopWatch1.Start ( );  
                while ( true )  
                {  
                    if ( this.stopWatch1.ElapsedMilliseconds >= 500 )  
                    {  
                        this.stopWatch1.Stop ( );  
                        break;  
                    }  
                }  
                Auxiliaries axil = new Auxiliaries ( );  
                if ( Globals.diariesTable == null )  
                {  
                    axil.createDiariesTable ( "diaries" );  
                } 
    I think I use it here to create an artificial delay because the next process encroaches onto the previous one.
    AlexB
    Monday, September 22, 2008 9:34 PM
  •  Interesting.  I see how you could use a Stopwatch to create delays, although I'd probably just do a "System.Threading.Thread.Sleep(500)" which would appear to achieve the same result.  I don't think this will help me though.  I use Timers so that certain methods are called periodically without needing to pause my interface thread.
    Tuesday, September 23, 2008 7:14 PM
  •  I believe you are still missing a point. I don't want to put the thread to sleep. I want it to continue doing what it is doing. This thing works for me exactly as I expected. The other piece of code is being executed and this one is put on the grind to wait.

    You can easily use StopWatch to run periodic processes as I said. Once your assigned time is over, restart the stopwatch again.

    AlexB
    Tuesday, September 23, 2008 7:35 PM
  • Thanks for your comments.  I am starting to understand your point that there is more than one way to structure a periodic event.

    By the way, I noticed an hour ago that .NET actually offers two completely different kinds of timers: System.Windows.Forms.Timer and System.Threading.Timer.  When you mentioned at the beginning of this thread that you have had bad experiences with timers, which of these two were you referring to?
    • Edited by Fastrak Wednesday, September 24, 2008 9:57 PM
    Wednesday, September 24, 2008 9:57 PM
  •  I expected a bit more awareness on your part:) Yep, I actually meant both. It's always been my desire to pinpoint the weeknesses on the timer parts if they are confined to one class or the other. I could not for the life of me to come to a definitive conclusion. I've used both and always a lot of time has been wasted to make them work.
    AlexB
    Wednesday, September 24, 2008 11:32 PM
  • I may try getting rid of all the timers.  Still, if any Microsoft MVP could shed a little light on what might cause the stack trace I posted in the very first post in this thread, I'd be very interested in understanding the cause of this problem a little more deeply.
    • Proposed as answer by PdNet Monday, October 27, 2008 10:05 AM
    Thursday, September 25, 2008 12:49 AM
  • Hi I am using Visual Studio 2008
    I am Using a Thread for showing the Splash screen

    at the Start of the MDI declare the thread as public and intialize and start when it needed.
    After Complete the task of the thread I call Threading.Thread.abort

    But Some how Second time the MDI Form is Called and hit the declaration of that Thread where I am declaring as ....

    Public TimerShowSplash As New Threading.Thread(AddressOf frmMDIMain.LoadPlashScreen)



    Then throws the thread Abort Exception
    • Edited by PdNet Thursday, October 30, 2008 7:08 AM
    Monday, October 27, 2008 10:31 AM
  •  Hi I am using vb.net 2008

    This is a C# forum.

    AlexB
    Monday, October 27, 2008 1:24 PM
  • Forget about vb.net or C#
    Please, Tell me the solution on visual studio


     am Using a Thread for showing the Splash screen

    at the Start of the MDI declare the thread as public and intialize and start when it needed.
    After Complete the task of the thread I call Threading.Thread.abort

    But Some how Second time the MDI Form is Called and hit the declaration of that Thread where I am declaring as ....

    Public TimerShowSplash As New Threading.Thread(AddressOf frmMDIMain.LoadPlashScreen)



    Then throws the thread Abort Exception
    Thursday, October 30, 2008 7:09 AM
  • Thread.Abort is obvolete as I understand. To my recall it is marked as such in the documentation. It is not recommended. To terminate threads you should use Monitor class or other asynchronous classes.

    I cannot visualize exactly your situation because (perhaps) the way you phrased it (?) but I suspect that this could  be the reason. What do you mean by "hit the declaration of the thead?" Do you reuse a thread with the same name second time around? Don't do it. It never works. You must let kernel manage its threads.

    AlexB
    Thursday, October 30, 2008 2:25 PM
  • How Can I use Monitor Class?

    hit the declaration of the thead? means When the Same Form Load Again.
    Friday, October 31, 2008 7:22 AM
  •  Monitor Class.

    Code Samples With a method description.

    An MSDN code sample.

    I cannot help more. Yesterday I tried to implement Monitor for one of my tasks and could not really debug it. If I don't crack it later today in about 2-3 hours I will have to post for help. If I do, I will come back with more insight.

    AlexB
    Friday, October 31, 2008 3:16 PM