Search

Control.Invoke exception handling by David A Nelson

Closed
as Won't Fix Help for as Won't Fix

12
0
Sign in
to vote
Type: Bug
ID: 386582
Opened: 12/4/2008 1:11:21 PM
Access Restriction: Public
0
Workaround(s)
6
User(s) can reproduce this bug
Control.Invoke rethrows any exception which occurs during the invoked operation on the original thread which called Invoke. However, the stack trace of the original is lost in the process. Instead of simply rethrowing the exception, Control.Invoke should wrap the thrown exception in a new exception to preserve the original stack trace. It should be up to the calling method to determine which is more important: the original stack trace of the exception, or rethrowing the original exception type.

Control.Invoke also strips off any outer exceptions by calling GetBaseException in the InvokeMarshaledCallbacks method. These outer exceptions often contain important information about the context in which the underlying exception occurred, and should not simply be stripped off. Again, it should be up to the caller to determine how to deal with the thrown exception; Control.Invoke should not make unfounded assumptions.

These problems are preventing us from getting critical debugging information from our applications in production. BeginInvoke/EndInvoke do not suffer from the same problems, however we do not have the option of switching; we are using the SynchronizationContext class in a library which is not WinForms-specific, and the WindowsFormsSynchronizationContext is hard coded to use Control.Invoke. I am not aware of any workarounds that are not WinForms-specific, which is unacceptable. Our apps are simply failing and we have no way of finding out why.
Details (expand)
Product Language
English

Version

Visual Studio 2008
Operating System
Windows XP Professional
Operating System Language
English
Steps to Reproduce
using System;
using System.Threading;
using System.Windows.Forms;
public class Form1 : Form
{
protected override void OnLoad(System.EventArgs e)
{
Thread newThread = new Thread(DoInvoke);
newThread.Start();
}
public void DoInvoke()
{
Invoke(new MethodInvoker(() =>
{
try
{
throw new Exception("Operation failed!");
}
catch (Exception ex)
{
throw new Exception("An exception was thrown by an asynchronous exception.", ex);
}
}));
}
}
Actual Results
System.Exception was unhandled
Message="Operation failed!"
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.Invoke(Delegate method)
at Form1.DoInvoke() in <AppPath>\Form1.cs:line 13
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Expected Results
Exception was unhandled
Message="An exception was thrown by an asynchronous exception."
Source="ControlInvokeStackTrace"
StackTrace:
at Form1.<.cctor>b__0() in <AppPath>\Form1.cs:line 14
at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.Invoke(Delegate method)
at Form1.OnLoad(EventArgs e) in <AppPath>\Form1.cs:line 23
at System.Windows.Forms.Form.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow)
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 System.Windows.Forms.Application.Run(Form mainForm)
at ControlInvokeStackTrace.Program.Main() in C:\Documents and Settings\dnelson\Local Settings\Application Data\Temporary Projects\ControlInvokeStackTrace\Program.cs:line 18
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()
InnerException:
Message="Operation failed!"
Source="ControlInvokeStackTrace"
StackTrace:
at Form1.<.cctor>b__0() in <AppPath>\Form1.cs:line 10
InnerException:
TAP Code (if applicable)
 
      You can indicate your satisfaction with how Microsoft handled this issue by completing this quick 3 question survey. [Details]

 

File Attachments
0 attachments
Sign in to post a comment.
Posted by darkmark327 on 4/22/2011 at 8:54 PM
Wow. This has been biting me for years with strange un-reproducable errors from customers because I was catching the outer exception. I'd see these "impossible" error reports once in a while, convinced that I was catching the exceptions in question. And now I find out that I've been lied to all along. Unbelievable.
Posted by Rasmus V Hansen on 4/12/2011 at 5:51 AM
A (ugly ugly) workaround is to log errors in the code that is invoked,
so instead of

control.Invoke(new Action(() => DoStuff());

Do:

control.Invoke(new Action(delegate
                    {
                        try
                        {
                            DoStuff();
                        }
                        catch (Exception ex)
                        {
                            // Log here since invoke swallows the stack trace
                            throw;
                        }
                    }));
Posted by Microsoft on 1/13/2009 at 7:08 PM
Thanks for your feedback on the .NET Framework!

Based on your description, this seems an urgent issue you wanted to address in order to unblock you from getting debugging info from your customer. If that is the case, I would suggest you firing servicing request through your company's servicing channel, if there is service agreement between your company and Microsoft.

We'll consider improving the exception handling mechanism for Control.Invoke(...) in next release. However this wouldn't be able to bring you the immediate help for your current customer facing issue.

Thanks!
UIFx Team
Posted by David A Nelson on 12/16/2008 at 8:12 AM
wyck,

The problem is that I need stack traces from production code. Changing debugger options in the IDE won't help any.
Posted by Wyck on 12/16/2008 at 8:00 AM
I'll second this, in spirit. Right now I have to change the behaviour in the exceptions window. For example, I was receiving a System.ArgumentOutOfRangeException. I changed it to break when the exception is thrown (by enabling the checkbox for System.ArgumentOutOfRangeException in the exceptions window). But for general exceptions, this is undesirable. You probably want to be able to break before an unhandled exception is passed to the other thread.

But I totally agree that if the exception is going to be unhandled, you want the inner stack trace somehow! There really has to be some kind of solution put forth for this.
Posted by Microsoft on 12/4/2008 at 9:32 PM
Thanks for your feedback.

We are escalating this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.

Thank you,
Visual Studio Product Team
Sign in to post a workaround.