|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
exception not propagating correctlyno spam MSDN alias since Microsoft changed the no spam alias rules and didn't tell anyone (you have to re-register a no spam alias to get a special domain extension in order for Microsoft to respond to posts). ---------- This refers to KB article #836674 (http://support.microsoft.com/?kbid=836674). I encountered the bug described in that article, but neither of the workarounds are entirely satisfactory. The first workaround, creating the App.config file, only seems to work when making a debug build. The second workaround solves the problem, but the process of re-throwing the exception causes the stack trace contained in the exception to be reset. The result is that when the exception is finally caught, the stack trace shows the call stack at the point where the ThreadExceptionEventHandler re-threw it, instead of where the exception was originally thrown. So, is there any way around this? Can I somehow throw the exception without having its stack trace altered? I don't want to change the code that eventually catches the exception to deal with this, I would like to simply get the behavior as it should be if this bug didn't exist at all. The original thread was:
http://tinyurl.com/44ta2 I mention it because someone did suggest throwing with no arguments, but that was tried and wouldn't even build. RRIMSDN wrote: Show quoteHide quote > Note this is a repost of an earlier thread (from Dec 2004) under my new, > no spam MSDN alias since Microsoft changed the no spam alias rules and > didn't tell anyone (you have to re-register a no spam alias to get a > special domain extension in order for Microsoft to respond to posts). > > ---------- > > This refers to KB article #836674 > (http://support.microsoft.com/?kbid=836674). I encountered the bug > described in that article, but neither of the workarounds are entirely > satisfactory. > > The first workaround, creating the App.config file, only seems to work > when making a debug build. > > The second workaround solves the problem, but the process of re-throwing > the exception causes the stack trace contained in the exception to be > reset. The result is that when the exception is finally caught, the > stack trace shows the call stack at the point where the > ThreadExceptionEventHandler re-threw it, instead of where the exception > was originally thrown. > > So, is there any way around this? Can I somehow throw the exception > without having its stack trace altered? I don't want to change the code > that eventually catches the exception to deal with this, I would like to > simply get the behavior as it should be if this bug didn't exist at all. Hi RRIMSDN,
Thanks for your posting! I have viewed that KB and did some test for this. Yes, for the first workaround, it really does not work for project release build. But for the second workaround, does the following way makes sense to you: Application.ThreadException+=new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) { MessageBox.Show(e.Exception.StackTrace); } That is do not throw a new exception in ThreadException method, just show out the stacktrace in ThreadException. This will result in the same StackTrace. Anyway, if you still have any concern, please feel free to tell me. Thanks ================================================================== Thank you for your patience and cooperation. If you have any questions or concerns, please feel free to post it in the group. I am standing by to be of assistance. Best regards, Jeffrey Tan Microsoft Online Partner Support Get Secure! - www.microsoft.com/security This posting is provided "as is" with no warranties and confers no rights. We know how to get the stack trace; what we really want to know is how
we can re-throw the exception while preserving that stack trace. We want the original stack trace to be part of the exception thrown from this work around. We know we can put the original exception as an inner exception to preserve it, but we don't want to do that because then we end up changing the type of exception thrown, and we want to preserve the original exception type. Basically all we want to know is if there is a way to throw the exception while preserving the stack trace. Is there any way to do that? thanks Jeffrey Tan[MSFT] wrote: Show quoteHide quote > Hi RRIMSDN, > > Thanks for your posting! > > I have viewed that KB and did some test for this. > > Yes, for the first workaround, it really does not work for project release > build. > > But for the second workaround, does the following way makes sense to you: > > Application.ThreadException+=new > System.Threading.ThreadExceptionEventHandler(Application_ThreadException); > > private static void Application_ThreadException(object sender, > System.Threading.ThreadExceptionEventArgs e) > { > MessageBox.Show(e.Exception.StackTrace); > } > > That is do not throw a new exception in ThreadException method, just show > out the stacktrace in ThreadException. This will result in the same > StackTrace. Anyway, if you still have any concern, please feel free to tell > me. Thanks > ================================================================== > Thank you for your patience and cooperation. If you have any questions or > concerns, please feel free to post it in the group. I am standing by to be > of assistance. > > Best regards, > Jeffrey Tan > Microsoft Online Partner Support > Get Secure! - www.microsoft.com/security > This posting is provided "as is" with no warranties and confers no rights. > If you throw a *new* application exception, can you set the new
exceptions InnerException property to the current exception? You should then be able to get the stack trace information from the InnerException. Just a thought, Chris Hi RRIMSDN,
Yes, I see your concern. Based on my experience, this can not be done. I think the Chris's suggestion of storing the original exception as the innerexception is a good workaround for this issue, althrough I see that you did not like this workaround. May I ask why you MUST re-throw the exception in ThreadException event handler? I suspect you only want to intercept all the exceptions in the application and display its details information, so I think ThreadException event handler which acts as a global handler should meet your need. If I misunderstand you, please feel free to tell me, thanks. ================================== Thank you for your patience and cooperation. If you have any questions or concerns, please feel free to post it in the group. I am standing by to be of assistance. Best regards, Jeffrey Tan Microsoft Online Partner Support Get Secure! - www.microsoft.com/security This posting is provided "as is" with no warranties and confers no rights. We must rethrow because we don't want duplicate code for handling this
work around case from our other cases, and we don't want to show the stack trace, we want to log it and perhaps do other things further up the call stack, and not necessarily right at this work around's spot. The managed part of the app is controlled/created by unmanaged code, so we need to translate the exception information into something that can be returned to the unmanaged app. The unmanaged app is the one that has to deal with the exception. At this point, we will use the workaround of wrapping it in an inner exception, even though that means we have to change the code that catches the exception. Is this problem expected (or already) fixed in the next version, 2005, of Visual Studio? thanks Jeffrey Tan[MSFT] wrote: Show quoteHide quote > Hi RRIMSDN, > > Yes, I see your concern. Based on my experience, this can not be done. I > think the Chris's suggestion of storing the original exception as the > innerexception is a good workaround for this issue, althrough I see that > you did not like this workaround. > > May I ask why you MUST re-throw the exception in ThreadException event > handler? I suspect you only want to intercept all the exceptions in the > application and display its details information, so I think ThreadException > event handler which acts as a global handler should meet your need. If I > misunderstand you, please feel free to tell me, thanks. > ================================== > Thank you for your patience and cooperation. If you have any questions or > concerns, please feel free to post it in the group. I am standing by to be > of assistance. > > Best regards, > Jeffrey Tan > Microsoft Online Partner Support > Get Secure! - www.microsoft.com/security > This posting is provided "as is" with no warranties and confers no rights. > Hi RRIMSDN,
Thanks very much for your feedback! Yes, I see your concern, your have placed an exception handler in somewhere, so you wanted forward the unhandled exception from the ThreadException handler to this exception handler. Then there is not much code that you have to modify. But currently, I did not think of a perfect solution for this issue, and some extra modification for code is necessary. I am not sure if VS.net 2005 will finally fix this issue, you may download the lastest beta version of VS.net2005 and did some test on it. Also, I will forward your concern for this issue to the owner of that KB and our product team. Hope this helps. Thank you for your patience and cooperation. If you have any questions or concerns, please feel free to post it in the group. I am standing by to be of assistance. Best regards, Jeffrey Tan Microsoft Online Partner Support Get Secure! - www.microsoft.com/security This posting is provided "as is" with no warranties and confers no rights. I need to be able to preserve an exception Stack Trace for a different
reason. I am writing asynchronous objects. Like a socket object. Here is some example code: private void cmdCauseAsynchronousException_Click(object sender, System.EventArgs e) { log.Write("Calling Begin..."); BeginTask(new AsyncCallback(TaskCompleteCallbackProcessor), null); log.Write("Begin called"); } private void TaskCompleteCallbackProcessor(IAsyncResult asyncResult) { log.Write("Callback calling end"); try { EndTask(asyncResult); log.Write("End called"); } catch(Exception e) { string ex = ""; Exception current = e; while( current != null ) { ex = "Exception:\r\n" + current.Message + "\r\n" + current.StackTrace + "\r\n" + ex; current = current.InnerException; } log.Write("Exception while calling end" + ex); } } private IAsyncResult BeginTask(AsyncCallback Callback, object State) { CallerAsyncResult callerAsyncResult = new CallerAsyncResult(Callback, State); ThreadPool.QueueUserWorkItem(new WaitCallback(PerformAsyncTask), callerAsyncResult); return callerAsyncResult; } private void PerformAsyncTask(object State) { CallerAsyncResult callerAsyncResult = (CallerAsyncResult)State; try { // Task try block // Simulate task Thread.Sleep(TimeSpan.FromMilliseconds(500.00)); // Simulate task throwing exception throw new Exception("Junk that is garbage"); } catch(Exception e) { callerAsyncResult.Complete(e); } callerAsyncResult.Complete(null); } private void EndTask(IAsyncResult asyncResult) { CallerAsyncResult callerAsyncResult = (CallerAsyncResult)asyncResult; callerAsyncResult.WaitForCompletion(); if(callerAsyncResult.exception != null) throw new Exception(callerAsyncResult.exception.Message, callerAsyncResult.exception); } public class CallerAsyncResult : IAsyncResult { protected int isCompleted = 0; protected int invokedCallback = 0; internal protected bool completedSynchronously = true; protected ManualResetEvent asyncOperationCompletedEvent = null; protected object asyncState = null; protected AsyncCallback callback = null; internal protected Exception exception = null; internal protected object operationResult = null; public CallerAsyncResult(AsyncCallback CallersCallback, object State) { asyncState = State; callback = CallersCallback; asyncOperationCompletedEvent = new ManualResetEvent(false); } public virtual void ReInit(AsyncCallback CallersCallback, object State) { completedSynchronously = true; asyncOperationCompletedEvent.Reset(); asyncState = State; callback = CallersCallback; isCompleted = 0; invokedCallback = 0; exception = null; } public virtual void Complete(Exception e) { this.exception = e; Complete(); } public virtual void Complete(object OperationResult) { operationResult = OperationResult; Complete(); } private void Complete() { if(Interlocked.Increment(ref isCompleted) == 1) { asyncOperationCompletedEvent.Set(); } PerformCallback(); } private void PerformCallback() { if(Interlocked.Increment(ref invokedCallback)==1) { if(callback != null) { callback(this); } } } public virtual void WaitForCompletion() { if(isCompleted == 0) { asyncOperationCompletedEvent.WaitOne(); } } public virtual void ClearObjectReferencesForReuse() { asyncState = null; callback = null; exception = null; } public object AsyncState { get { return asyncState; } } public WaitHandle AsyncWaitHandle { get { return asyncOperationCompletedEvent; } } public bool CompletedSynchronously { get { return completedSynchronously; } } public bool IsCompleted { get { return (isCompleted != 0); } } } Now here is my problem. As you can see where I implemented the work-around and set the original exception to be the InnerException of a new Exception. "throw new Exception(callerAsyncResult.exception.Message, callerAsyncResult.exception);" I'd much rather be able to do this: "thow callerAsyncResult.exception;" and have the exception append to its existing stack trace rather than throw out the stack trace that it already has. Here is why, suppose I have several nested layers of asynchronous streams with a socket deep underneath. I wish to make asynchronous calls to these streams and I wish to selectively catch the socket exceptions from the top to detect a network faliure. If I create a new exception then the exception type is not preserved making this impossible. I suppose I could implement the Exception.GetBaseException() method to work
around this problem. I will need to use Exception.GetBaseException() for all my high level try catch blocks. Say I have the following high level code: NetworkStream nsBaseStream = new NetworkStream(connectedSocket); MyCustomStream ms = new MyCustomStream(nsBaseStream); IAsyncResult res = ms.BeginRead(null, null); try { ms.EndRead(res); } catch(SecurityException se) { // handle security exception, say code access security denies a call to something that MyStream uses } catch(SocketException se) { // If the exception type was not preserved I would not catch this // Since I can't rethrow and save an InnerException simultaneously then // I must create a new exception, but if I create a new exception then // this catch block will never execute because the exception type will probably change // If I re-throw the exception then I will lose the original stack trace } Versus this code which makes use of GetBaseException NetworkStream nsBaseStream = new NetworkStream(connectedSocket); MyCustomStream ms = new MyCustomStream(nsBaseStream); IAsyncResult res = ms.BeginRead(null, null); try { ms.EndRead(res); } catch(SecurityException se) { // handle security exception, say code access security denies a call to something that MyStream uses } catch(Exception e) { Exception baseEx = e.GetBaseException(); if(typeof(SocketException ) == baseEx.GetType()) { // handle socket exception that should have bubbled up from low level code if the socket connection to the remote host fails } else { // here is the problem again, I have solved one problem to create another // If I re-throw then I'll lose the stack trace, or perhaps just throw will preserve it? throw; // ?? } } If this last code example works it is a pretty inelegant work-around. Especially if I want an easy to use code library. Imagine trying to educate people on how to handle exceptions from your library using the GetBaseException method. I have solved my problems by creating the following class:
public class AsynchronousException : ApplicationException { public AsynchronousException(Exception innerException) : base(innerException.Message, innerException) { } public override Exception GetBaseException() { return base.GetBaseException (); } } I have changed my End Task Event to throw this exception when an asynchronous exception is thrown. private void EndTask(IAsyncResult asyncResult) { CallerAsyncResult callerAsyncResult = (CallerAsyncResult)asyncResult; callerAsyncResult.WaitForCompletion(); if(callerAsyncResult.exception != null) { throw new AsynchronousException(callerAsyncResult.exception.Message, callerAsyncResult.exception); } } If an AsychronousException is thrown when I call EndTask then I know that I must get the base exception to really see what is going on: log.Write("Callback calling end"); try { EndTask(asyncResult); log.Write("End called"); } catch(AsynchronousException ae) { Exception baseException = ae.GetBaseException(); if(baseException.GetType() == typeof(SocketException)) { // Handle this type of exception here } else { // Hande other asynchronous exceptions } } If another Exception is thrown it can be caught by another catch block. Show quoteHide quote "Chris Tanger" wrote: > > I suppose I could implement the Exception.GetBaseException() method to work > around this problem. I will need to use Exception.GetBaseException() for all > my high level try catch blocks. > > Say I have the following high level code: > > NetworkStream nsBaseStream = new NetworkStream(connectedSocket); > > MyCustomStream ms = new MyCustomStream(nsBaseStream); > > IAsyncResult res = ms.BeginRead(null, null); > > try > { > ms.EndRead(res); > } > catch(SecurityException se) > { > // handle security exception, say code access security denies a call to > something that MyStream uses > } > catch(SocketException se) > { > // If the exception type was not preserved I would not catch this > // Since I can't rethrow and save an InnerException simultaneously then > // I must create a new exception, but if I create a new exception then > // this catch block will never execute because the exception type will > probably change > // If I re-throw the exception then I will lose the original stack trace > } > > > Versus this code which makes use of GetBaseException > > > NetworkStream nsBaseStream = new NetworkStream(connectedSocket); > > MyCustomStream ms = new MyCustomStream(nsBaseStream); > > IAsyncResult res = ms.BeginRead(null, null); > > > try > { > ms.EndRead(res); > } > catch(SecurityException se) > { > // handle security exception, say code access security denies a call to > something that MyStream uses > } > catch(Exception e) > { > Exception baseEx = e.GetBaseException(); > if(typeof(SocketException ) == baseEx.GetType()) > { > // handle socket exception that should have bubbled up from low > level code if the socket connection to the remote host fails > } > else > { > // here is the problem again, I have solved one problem to > create another > // If I re-throw then I'll lose the stack trace, or perhaps > just throw will preserve it? > throw; // ?? > } > } > > > If this last code example works it is a pretty inelegant work-around. > Especially if I want an easy to use code library. Imagine trying to educate > people on how to handle exceptions from your library using the > GetBaseException method. > > > >
Other interesting topics
Clicking a button and pressing Enter key act different in MDI clie
OT: Replacement for Adobe Acrobat Multiple Events in a single method Drag Drop Data pictures to my Form wiring events .NET framework apps in Terminal Server New Thread Drag and Drop Message from outlook datagrid memory leak? Outlook Style Calendar Control |
|||||||||||||||||||||||