2

Got a strange problem: in a complex camera control program I'm working on, I use an SDK with a C# wrapper that was programmed by someone else. I include the wrapper as a separate project within the same solution. My own code is a WPF project that uses numerous calls into the SDK.

Everything synchronous works fine. However, depending on camera responses, the SDK occasionally sends asynchronous responses, usually in the form of throwing a custom exception with info about an error the camera reports. I implemented this using

try { ... } catch (ThisExceptionType) { ... }

However, NO exception ever gets caught. When an exception situation occurs, VisualStudio breaks, shows me the code where the SDK throws it and reports "ThisExceptionType was unhandled by user code", also showing the details of the exception condition (meaning it was apparently thrown properly). I verified that the exception corresponds with the error condition I created, so I'm sure I'm not looking at the wrong part of my code.

For testing purposes, I also replaced the line in the SDK where it throws ThisExceptionType with a standard exception, such as throw new ArgumentException("Test"); Same result: when changing my catch to catch (ArgumentException), I still cannot catch the condition and get a similar unhandled-by-user-code error.

Here's how the SDK throws the exception:

void CallEntryPoint( ...)
    {
        eNkMAIDResult result = _md3.EntryPoint(...);

        switch (result)
        {
            // Note: Ignore these return values
            case eNkMAIDResult.kNkMAIDResult_NoError:
            case eNkMAIDResult.kNkMAIDResult_Pending:
                break;

            default:
                throw new NikonException(...);
        }
    }

What am I missing here? Sorry if this is a simple issue - I'm pretty experienced in general programming but have not worked much with VisualStudio, and not a whole lot in C#, either.

UPDATE: According to the wrapper's author (this is actually Thomas Dideriksen's Nikon SDK wrapper), "when you're writing WPF or WinForms application, the C# wrapper relies on the inherent windows message queue to fire events on the UI thread."

He also states that the wrapper processes all camera tasks sequentially, so I guess my statement was incorrect about the wrapper throwing asynchronous exceptions - all code examples for the wrapper use the same try { ... } catch (ThisExceptionType) { ... } approach. For good measure, I tried some of your suggestions, for instance by hooking a handler to AppDomain.CurrentDomain.UnhandledException, but that approach failed to catch the exception, as well.

Any other ideas why this may be happening?

Lon
  • 73
  • 2
  • 11
  • 2
    the problem is the asynchronous processing. Exceptions from other threads are not caught within the main thread. There are a lot of posts concerning this topic like [this](http://stackoverflow.com/questions/5983779/catch-exception-that-is-thrown-in-different-thread) – Mong Zhu Jun 27 '16 at 13:54
  • I guess you handle the asynchronous messaging via events; could you post the code? – Mong Zhu Jun 27 '16 at 13:55
  • "the SDK occasionally sends *asynchronous* responses": Sounds like the exception is not actually being thrown between the try and the catch. Can you include your code that interacts with the SDK? I assume your code must do something that causes the SDK to go off and do its thing and then eventually throw the exception. If the SDK modern code that uses `Task`/`async`, [you should be able to throw a try/catch around an `await`](http://stackoverflow.com/a/19865613/424129). – 15ee8f99-57ff-4f92-890c-b56153 Jun 27 '16 at 14:00
  • @EdPlunkett, guess you're right that the exception may not be triggered in time for the catch to get it. Unfortunately, the SDK wrapper apparently does not use the Task / async approach (see code example I added above). Is my only option here to modify the SDK wrapper code? – Lon Jun 27 '16 at 14:51
  • @Lon I might look at the [unhandled exception](http://stackoverflow.com/a/1472522/424129) mechanism. If you need to do anything more with the exception than report it to the user, it might get ugly, but I'd almost certainly prefer that to maintaining my own version of somebody else's SDK wrapper. – 15ee8f99-57ff-4f92-890c-b56153 Jun 27 '16 at 15:05

1 Answers1

1

This article on MSDN may help. https://msdn.microsoft.com/en-us/library/dd997415(v=vs.110).aspx

There are differences in handling exceptions using Tasks in C#. Hopefully that will give a run down on different techniques you can use to handle the exceptions appropriately.

From the MSDN article:

Unhandled exceptions that are thrown by user code that is running inside a task are propagated back to the calling thread, except in certain scenarios that are described later in this topic. Exceptions are propagated when you use one of the static or instance Task.Wait or Task.Wait methods, and you handle them by enclosing the call in a try/catch statement. If a task is the parent of attached child tasks, or if you are waiting on multiple tasks, multiple exceptions could be thrown.

And there are a couple solutions provided:

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );

      try
      {
          task1.Wait();
      }
      catch (AggregateException ae)
      {
          foreach (var e in ae.InnerExceptions) {
              // Handle the custom exception.
              if (e is CustomException) {
                  Console.WriteLine(e.Message);
              }
              // Rethrow any other exception.
              else {
                  throw;
              }
          }
      }
   }
}

public class CustomException : Exception
{
   public CustomException(String message) : base(message)
   {}
}
// The example displays the following output:
//        This exception is expected!

Or you can do this:

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );

      while(! task1.IsCompleted) {}

      if (task1.Status == TaskStatus.Faulted) {
          foreach (var e in task1.Exception.InnerExceptions) {
              // Handle the custom exception.
              if (e is CustomException) {
                  Console.WriteLine(e.Message);
              }
              // Rethrow any other exception.
              else {
                  throw e;
              }
          }
      }
   }
}

public class CustomException : Exception
{
   public CustomException(String message) : base(message)
   {}
}
// The example displays the following output:
//        This exception is expected!

I hope that helps!

BHubbard
  • 76
  • 4
  • For starters, thanks to all of you for responding so quickly. Guess I need to read up on C# task threading - this is not something I used before. For clarification, the exceptions I may be receiving are error messages, not regular responses, so I can't use any solution that waits because nothing may ever come back. – Lon Jun 27 '16 at 14:21