|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Exception handling bug?: Control.Invoke()I'm currently working on exception handling for a multithreaded component. It looks like I've ran into a framework bug when inner exceptions is concerned. The code: internal delegate void TcpipMethod(TcpipSocket socket); private TcpipMethod _internalReceive; private void CallbackReceive(IAsyncResult result) { TcpipCloseMode closeMode = TcpipCloseMode.None; TcpipSocket socket = result.AsyncState as TcpipSocket; try { .. .. if (_syncControl != null) _syncControl.Invoke(_internalReceive, new object[] { socket }); else InternalReceive(socket); } catch (ObjectDisposedException) { } catch (Exception exception) { if (!(exception is SocketException && ((SocketException)exception).ErrorCode == 10054)) { if (_syncControl != null) _syncControl.Invoke(_internalError, new object[] { socket, exception }); else InternalError(socket, exception); } } } private void InternalReceive(TcpipSocket socket) { try { DoReceive(new TcpipEventArgs<T>(socket)); } catch (Exception e) { throw new TcpipException("Exception in receive event.", e); } } The CallbackReceive method runs on its own asynchronous thread. The property _syncControl is filled with UI control. This would allow me to synchronize the read event (DoReceive) to the application main thread. This event is called through the method InternalReceive which is the actual method being synchronized. The event caller (DoReceive) is placed in a try..catch block to capture any exceptions that occur inside the user event. The reason for this approach is to make sure user exceptions do not break the component. ObjectDisposedException is one that could potentially break the component, as it is generated by the user, and not in response to attempting to use a closed socket inside the component. The try block then raises a new exception (TcpipException) which takes the caught exception as the inner exception parameter. One would expect this raised exception be propagated back to the callback method as the documentation for Control.Invoke() explains. However, in the catch block inside the callback method, the exception is NOT the newly raised exception TcpipException, but it is the inner exception itself! If inside the user event an ObjectDisposed exception would have been thrown, this would be the type of the caught exception in the callback try..catch block. When I re-raise the exception without specifying the inner exception, it works fine and the callback method will catch the re-raised exception. But as soon as an inner exception is specified, the re-raised exception gets ignored somehow where the inner exception takes its place? I am not sure if this intended behaviour, but to me this sure doesn't seem to be the intended way. I've searched for any information on this subject, but I haven't found any exceptional situations to this. Effectively, it appears I can not 'remap' exceptions thrown in Control.Invoke'd methods while this (in my eyes) expected behaviour is critical for the component to operate... |
|||||||||||||||||||||||