locked
Catching Exceptions from unmanaged code inside my try/catch? RRS feed

  • Question

  • I am doing USB communication asynchronously. During communication, if I unplug the USB cable, my app crashes. I am trying to find a way to fix this.

    Right before I try to read a response to my write packet (the read is where I crash), I have been able to use Marshal.GetLastWin32Error() to get an error code of 0x48f. This is a "The device is not connected" error. If I check against this error code, and try to throw an exception there prior to my read, it does not work. I have also tried catching SEHExceptions, Win32Exceptions, ComExceptions... all with no luck. I also put a HandleProcessCorruptedStateExceptions attribute on the read method.

    How can I catch this exception from unmanaged code in my try/catch block without my app crashing?

    One more note. When I run the app from the bin\debug folder, hit read, unplug, I get a MyApp stopped working. It thinks for a minute, then I get the option to debug. When I do that, it breaks in the catch block inside my read statement and says my exception was not handled. Please Help!!!!!

    Wednesday, March 30, 2011 4:39 PM

Answers

  • Ok, I think I got it figured out, and it is a threading issue. Lets see if I can explain it. I have a USB class with all of my reading/writing stuff in it. One method in there is called ReadDataFile(). This is the worker method for my ReadWorker delegate and thus reading of the data file is on an asynchronous background thread.

    Nested inside the ReadDataFile() method, between all the reading and writing, I'm using a FileStream with an AsyncCallback seen below:

    if (mStream.CanRead)
      mStream.BeginRead(buff, 0, REPORT_LENGTH, new AsyncCallback(OnReadData), buff);   //Setup the read and the callback;
    
    if (!mReadDone.WaitOne(2000, false))
      throw new CustomException(Resources.readPacketResponseError, new Exception("mReadDone.WaitOne() passed the 2000ms timeout!"));
    
    
    Inside OnReadData(), I have this code:

    private void OnReadData(IAsyncResult ar)
    {
      try
      {
        if (Marshal.GetLastWin32Error() == 0x48f)
          Debug.WriteLine("Device not connected (0x48f)!");
    
        mStream.EndRead(ar);  //end the current read
        mReadDone.Set();    //set the event so the other thread will continue
      }
      catch (IOException) { Debug.WriteLine("OnReadData() IOException"); }
      catch (NotSupportedException) { Debug.WriteLine("OnReadData() NotSupportedException"); }
      catch (ArgumentNullException) { Debug.WriteLine("OnReadData() ArgumentNullException"); }
      catch (ArgumentException) { Debug.WriteLine("OnReadData() ArgumentException"); }
      catch (InvalidOperationException) { Debug.WriteLine("OnReadData() InvalidOperationException"); }
      catch (OperationCanceledException) { Debug.WriteLine("OnReadData() OperationCanceledException"); }
      catch (Exception) { Debug.WriteLine("OnReadData() Exception"); }
    }
    
    

    This is where the trouble was. Originally I was throwing the errors I caught in OnReadData(), now I just print them to the output window. When it was crashing, the debugger would always take me to the mStream.EndRead(ar) line. Now, instead of crashing and getting stuck there, I actually catch the IOException (but don't throw it). Subsequently, I get into the throw new CustomException after the 2000ms timeout.

    It seems I can't throw an exception from OnReadData() b/c it is on a separate thread than ReadDataFile(). Does any of that make sense? 

    • Marked as answer by BBauer42 Thursday, March 31, 2011 8:11 PM
    Thursday, March 31, 2011 12:23 PM

All replies

  • Which version of .NET are you using?  

    James Michael Hare

    Blog: http://www.geekswithblogs.net/BlackRabbitCoder

    Twitter: @BlkRabbitCoder

    There are 10 kinds of people in the world: those who know binary and those who don't...

    Wednesday, March 30, 2011 4:59 PM
  • .NET Framework 4.0
    Wednesday, March 30, 2011 5:04 PM
  • Catching Exception then will catch all exceptions, both CLS and non-CLS compliant ones.  Non-CLS compliant exceptions are wrapped in RuntimeWrapperException.

    There's a good thread on this in Stack Overflow here: http://stackoverflow.com/questions/1531077/will-clr-handle-both-cls-complaint-and-non-cls-complaint-exceptions

    In earlier versions of .NET, catch (Exception) { } didn't catch non-CLS exceptions and you had to have a separate catch { } block.  However C# now wraps non-CLS exceptions and catch (Exception) handles those too.


    James Michael Hare

    Blog: http://www.geekswithblogs.net/BlackRabbitCoder

    Twitter: @BlkRabbitCoder

    There are 10 kinds of people in the world: those who know binary and those who don't...


    Wednesday, March 30, 2011 5:53 PM
  • Is it truly an exception?  Or an error code?

    James Michael Hare

    Blog: http://www.geekswithblogs.net/BlackRabbitCoder

    Twitter: @BlkRabbitCoder

    There are 10 kinds of people in the world: those who know binary and those who don't...

    Wednesday, March 30, 2011 5:55 PM
  • Interesting, b/c it doesn't catch the exception. It crashes the app. I wish I could give you a smaller version to test with but you would need the hardware too, so that wouldn't work. Any other ideas? If I wrap my entire ReadDataFile() method in a try/catch, and catch the generic exception, it still crashes.....
    Wednesday, March 30, 2011 5:56 PM
  • I would say the other question is does the native code truly throw an exception, or does it do something very brutal like an exit() call?

    Have you ever used WinDbg?  It would be interesting to throw the application under WinDbg and see what the actual exception being raised is.


    James Michael Hare

    Blog: http://www.geekswithblogs.net/BlackRabbitCoder

    Twitter: @BlkRabbitCoder

    There are 10 kinds of people in the world: those who know binary and those who don't...

    Wednesday, March 30, 2011 6:00 PM
  • Ok, I think I got it figured out, and it is a threading issue. Lets see if I can explain it. I have a USB class with all of my reading/writing stuff in it. One method in there is called ReadDataFile(). This is the worker method for my ReadWorker delegate and thus reading of the data file is on an asynchronous background thread.

    Nested inside the ReadDataFile() method, between all the reading and writing, I'm using a FileStream with an AsyncCallback seen below:

    if (mStream.CanRead)
      mStream.BeginRead(buff, 0, REPORT_LENGTH, new AsyncCallback(OnReadData), buff);   //Setup the read and the callback;
    
    if (!mReadDone.WaitOne(2000, false))
      throw new CustomException(Resources.readPacketResponseError, new Exception("mReadDone.WaitOne() passed the 2000ms timeout!"));
    
    
    Inside OnReadData(), I have this code:

    private void OnReadData(IAsyncResult ar)
    {
      try
      {
        if (Marshal.GetLastWin32Error() == 0x48f)
          Debug.WriteLine("Device not connected (0x48f)!");
    
        mStream.EndRead(ar);  //end the current read
        mReadDone.Set();    //set the event so the other thread will continue
      }
      catch (IOException) { Debug.WriteLine("OnReadData() IOException"); }
      catch (NotSupportedException) { Debug.WriteLine("OnReadData() NotSupportedException"); }
      catch (ArgumentNullException) { Debug.WriteLine("OnReadData() ArgumentNullException"); }
      catch (ArgumentException) { Debug.WriteLine("OnReadData() ArgumentException"); }
      catch (InvalidOperationException) { Debug.WriteLine("OnReadData() InvalidOperationException"); }
      catch (OperationCanceledException) { Debug.WriteLine("OnReadData() OperationCanceledException"); }
      catch (Exception) { Debug.WriteLine("OnReadData() Exception"); }
    }
    
    

    This is where the trouble was. Originally I was throwing the errors I caught in OnReadData(), now I just print them to the output window. When it was crashing, the debugger would always take me to the mStream.EndRead(ar) line. Now, instead of crashing and getting stuck there, I actually catch the IOException (but don't throw it). Subsequently, I get into the throw new CustomException after the 2000ms timeout.

    It seems I can't throw an exception from OnReadData() b/c it is on a separate thread than ReadDataFile(). Does any of that make sense? 

    • Marked as answer by BBauer42 Thursday, March 31, 2011 8:11 PM
    Thursday, March 31, 2011 12:23 PM
  • Hi BBauer42,

     

    EndXXX method needs to pass a parameter which pend asynchronous request to finish. Based on my experience, you can check IAsyncResult.IsCompleted Property to get a value which monitor the async operation has completed or not.

    Hope this helps,

    Thanks,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, March 31, 2011 2:07 PM
  • Ah, that makes sense.  Exceptions thrown on other threads won't pass to the main thread.

    James Michael Hare

    Blog: http://www.geekswithblogs.net/BlackRabbitCoder

    Twitter: @BlkRabbitCoder

    There are 10 kinds of people in the world: those who know binary and those who don't...

    Thursday, March 31, 2011 3:31 PM
  • Thanks all for your input. I'm all set now!
    Thursday, March 31, 2011 8:10 PM