2016-06-27 10 views
0

Ich habe ein seltsames Problem: In einem komplexen Kamerasteuerprogramm, an dem ich arbeite, verwende ich ein SDK mit einem C# -Wrapper, der von jemand anderem programmiert wurde. Ich schließe den Wrapper als separates Projekt innerhalb derselben Lösung ein. Mein eigener Code ist ein WPF-Projekt, das zahlreiche Aufrufe in das SDK verwendet.C# Kann keine Ausnahmen von einem anderen Projekt in derselben Lösung abfangen

Alles synchron funktioniert gut. Abhängig von den Antworten der Kamera sendet das SDK jedoch gelegentlich asynchrone Antworten, normalerweise in Form einer benutzerdefinierten Ausnahme mit Informationen zu einem Fehler, den die Kamera meldet. Ich implementiert diese mit

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

jedoch wird keine Ausnahme jemals gefangen. Wenn eine Ausnahmesituation auftritt, bricht VisualStudio, zeigt mir den Code, wo das SDK es auslöst und meldet, dass "ThisExceptionType vom Benutzercode nicht behandelt wurde", wobei auch die Details der Ausnahmebedingung angezeigt werden (was bedeutet, dass sie offensichtlich ordnungsgemäß ausgelöst wurde). Ich habe überprüft, dass die Ausnahme der Fehlerbedingung entspricht, die ich erstellt habe. Ich bin mir sicher, dass ich nicht auf den falschen Teil meines Codes schaue.

Zu Testzwecken I ersetzt auch die Zeile in der SDK, wo es ThisExceptionType mit einer Standard Ausnahme, wie throw new ArgumentException("Test"); gleiches Ergebnis führt: wenn meinen Fang catch (ArgumentException) ändern, ich kann immer noch nicht den Zustand fangen und eine ähnliche unhandled- erhalten By-User-Code Fehler.

Hier ist, wie das SDK die Ausnahme auslöst:

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(...); 
     } 
    } 

Was soll ich hier fehlt? Tut mir leid, wenn dies ein einfaches Problem ist - ich bin ziemlich erfahren in der allgemeinen Programmierung, habe aber nicht viel mit VisualStudio gearbeitet und auch nicht viel in C#.

UPDATE: Laut dem Autor Wrapper (dies ist eigentlich Thomas Dideriksen's Nikon SDK wrapper), „wenn Sie WPF oder WinForms-Anwendung schreiben, setzt der C# Wrapper auf der Warteschlange inhärenten Fenster Nachrichtenereignisse auf dem UI-Thread zu schießen.“

Er sagt auch, dass der Wrapper alle Kameraaufgaben der Reihe nach verarbeitet, also meine Aussage war falsch über den Wrapper asynchrone Ausnahmen werfen - alle Codebeispiele für den Wrapper verwenden die gleiche try { ... } catch (ThisExceptionType) { ... } Ansatz. Zum Glück habe ich einige Ihrer Vorschläge ausprobiert, zum Beispiel indem Sie einen Handler an AppDomain.CurrentDomain.UnhandledException angehängt haben, aber dieser Ansatz konnte die Ausnahme auch nicht abfangen.

Irgendwelche anderen Ideen, warum dies geschehen kann?

+2

das Problem ist die asynchrone Verarbeitung. Ausnahmen von anderen Threads werden nicht im Hauptthread abgefangen. Es gibt eine Menge Beiträge zu diesem Thema wie [this] (http://stackoverflow.com/questions/5983779/catch-exception-that-is-thrown-in-different-thread) –

+0

Ich denke, Sie behandeln die asynchrone Nachrichtenübermittlung über Ereignisse; Könntest du den Code posten? –

+0

"Das SDK sendet gelegentlich * asynchrone * Antworten": Klingt so, als würde die Ausnahme nicht zwischen Versuch und Fang geworfen. Können Sie Ihren Code einfügen, der mit dem SDK interagiert? Ich nehme an, dass Ihr Code etwas tun muss, das bewirkt, dass das SDK abgeht und seine Sache macht und dann schließlich die Ausnahme auslöst. Wenn der moderne SDK-Code 'Task' /' async' verwendet, [sollte es möglich sein, einen Versuch/Fang um ein 'warten' zu werfen] (http://stackoverflow.com/a/19865613/424129). –

Antwort

1

Dieser Artikel auf MSDN kann helfen. https://msdn.microsoft.com/en-us/library/dd997415(v=vs.110).aspx

Es gibt Unterschiede bei der Behandlung von Ausnahmen mit Aufgaben in C#. Hoffentlich gibt das einen run down über verschiedene Techniken, die Sie verwenden können, um die Ausnahmen angemessen zu behandeln.

Aus dem MSDN-Artikel:

Unbehandelte Ausnahmen, die durch Benutzercode geworfen werden, die innerhalb einer Task laufen zurück zu dem aufrufenden Thread propagierten, außer in bestimmten Szenarien, die weiter unten in diesem Thema beschrieben werden . Ausnahmen werden weitergegeben, wenn Sie eine der statischen Task Task.Wait oder Task.Wait Methoden verwenden, und Sie behandeln sie, indem Sie den Aufruf in einer try/catch-Anweisung einschließen.Wenn eine Aufgabe das übergeordnete untergeordnete Aufgaben ist oder wenn Sie auf mehrere Aufgaben warten, können mehrere Ausnahmen ausgelöst werden.

Und es gibt ein paar Lösungen zur Verfügung gestellt:

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! 

Oder Sie können dies tun:

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! 

Ich hoffe, das hilft!

+0

Für den Anfang, vielen Dank, dass Sie so schnell reagiert haben. Ich denke, ich muss über C# -Task-Threading nachlesen - das ist etwas, das ich vorher nicht benutzt habe. Zur Verdeutlichung sind die Ausnahmen, die ich möglicherweise erhalte, Fehlermeldungen, keine regulären Antworten, daher kann ich keine Lösung verwenden, die wartet, weil nie wieder etwas zurückkommt. – Lon