none
async Exception durchreichen

    Frage

  • Hallo!

    Ich möchte eine Exception, die ich (asynchron) in einer mit await aufgerufenen Methode abfange, an die aufrufende Methode zurückgeben, um sie dort zu behandeln.

    Aufrufende Methode:

    try                                                                 // Daten abrufen
    {
        tabSQL = await System.Threading.Tasks.Task<DataTable>.Run(() => ar_Global.ar_SQL_Server.getDynSQLServerDaten(zSQL, "Data Source=" + zServer + ";Initial Catalog=" + zDB + ";Integrated Security=True", "tabSQL"));
    }  
    catch (Exception ex)
    {
        MessageBox.Show("Die SQL-Abfrage konnte nicht erfolgreich ausgeführt werden!" + Environment.NewLine + Environment.NewLine +
                        ex.Message, "Bitte SQL-Anweisung prüfen ...", MessageBoxButton.OKCancel, MessageBoxImage.Stop);
    }


    aufgerufene Methode: (in ar_Global.dll)

    try { conn.Open(); }                                                                // Verbindung herstellen
    catch (System.Data.SqlClient.SqlException ex) {
        throw new Exception("Die SQL-Server-Verbindung konnte nicht hergestellt werden!", ex); }                                                        // Ausnahme auslösen, wenn die Verbindung nicht hergestellt werden konnte.
    

    Im Debugger wird bei einer Exception in der aufgerufenen Methode (conn.Open) die Exception jedoch nicht weitergeleitet, sondern als unbehandelte Exception gefeuert.

    Wie leite ich die Exception den dann weiter???

    Mittwoch, 7. Februar 2018 15:05

Antworten

  • Hi,
    wenn Du den Fehler nicht in der asynchronen Routine abfängst, kannst Du auch TaskCompletionSource nutzen. Dazu eine kleine Demo:

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
      class Program34
      {
        static void Main(string[] args)
        {
          try
          {
            Demo c = new Demo();
            c.Execute();
          }
          catch (Exception ex) { Console.WriteLine(ex.ToString()); }
          Console.WriteLine("Fertig, Abschluss mit beliebiger Taste");
          Console.ReadKey();
        }
    
        class Demo
        {
          internal void Execute()
          {
            TaskCompletionSource<int> tcs1 = new TaskCompletionSource<int>();
            Task<int> t1 = tcs1.Task;
    
            // Starten des asynchronen Hintergrund-Threads, der Fehler auslöst
            Task.Factory.StartNew(() =>
            {
              Thread.Sleep(1000);
              tcs1.SetException(new InvalidOperationException("Simulierter Fehler"));
            });
    
            // Ergebnis abwarten
            try
            {
              int result = t1.Result;
              Console.WriteLine("Ergebnis erhalten.");
            }
            catch (AggregateException e)
            {
              Console.WriteLine("Fehler aufgetreten:");
              Exception ex2 = e;
              while (ex2 != null)
              {
                Console.WriteLine("\n-------------------------------------------------\n{0}", ex2.ToString());
                ex2 = ex2.InnerException;
              }
            }
          }
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    • Als Antwort markiert perlfred Freitag, 9. Februar 2018 09:12
    • Bearbeitet Peter Fleischer Mittwoch, 14. Februar 2018 07:53 Schreibfehler
    Mittwoch, 7. Februar 2018 17:00

Alle Antworten

  • Übrigens: ist bei Dir "Nur eigener Code" unter "Extras, Optionen, Debugging, Allgemein" aktiviert. Dann versuch es noch mal nach Deaktivierung dieser Einstellung.


    wizend


    • Bearbeitet Wizend Mittwoch, 7. Februar 2018 16:58
    Mittwoch, 7. Februar 2018 16:35
  • Hi,
    wenn Du den Fehler nicht in der asynchronen Routine abfängst, kannst Du auch TaskCompletionSource nutzen. Dazu eine kleine Demo:

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
      class Program34
      {
        static void Main(string[] args)
        {
          try
          {
            Demo c = new Demo();
            c.Execute();
          }
          catch (Exception ex) { Console.WriteLine(ex.ToString()); }
          Console.WriteLine("Fertig, Abschluss mit beliebiger Taste");
          Console.ReadKey();
        }
    
        class Demo
        {
          internal void Execute()
          {
            TaskCompletionSource<int> tcs1 = new TaskCompletionSource<int>();
            Task<int> t1 = tcs1.Task;
    
            // Starten des asynchronen Hintergrund-Threads, der Fehler auslöst
            Task.Factory.StartNew(() =>
            {
              Thread.Sleep(1000);
              tcs1.SetException(new InvalidOperationException("Simulierter Fehler"));
            });
    
            // Ergebnis abwarten
            try
            {
              int result = t1.Result;
              Console.WriteLine("Ergebnis erhalten.");
            }
            catch (AggregateException e)
            {
              Console.WriteLine("Fehler aufgetreten:");
              Exception ex2 = e;
              while (ex2 != null)
              {
                Console.WriteLine("\n-------------------------------------------------\n{0}", ex2.ToString());
                ex2 = ex2.InnerException;
              }
            }
          }
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    • Als Antwort markiert perlfred Freitag, 9. Februar 2018 09:12
    • Bearbeitet Peter Fleischer Mittwoch, 14. Februar 2018 07:53 Schreibfehler
    Mittwoch, 7. Februar 2018 17:00
  • Hallo Peter!

    Vielen Dank, dass du dir wieder so viel Mühe gemacht hast, mein Problem zu lösen!!!

    Ich muss jetzt deine Lösung allerdings noch in WPF umsetzen.

    Viele Grüße Fred.

    Freitag, 9. Februar 2018 09:12
  • Hi Fred,
    in meiner Demo wird ide Klasse Demo genutzt. Diesen Code kannst Du problemlos in der ViewModel-Klasse nutzen. Da ist nichts ungewöhnliches umzusetzen.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Freitag, 9. Februar 2018 12:19
  • Hallo Peter!

    Deine Lösung habe ich jetzt umgesetzt. Funktioniert 100%ig!

    Nochmals vielen Dank für deine Hilfe!

    Fred. 

    Montag, 12. Februar 2018 12:00
  • Hallo Peter!

    Nun ist für mich doch noch ein Problem mit der TaskComplitationSource aufgetreten.

    Wie beendet man den Task, (sofort) beim Auftreten einer Exception? Bei throw ... geht es automatisch.

    Ich habe mal dein Beispiel genommen und eine weitere Exception hinzugefügt:

    // Starten des asynchronen Hintergrund-Threads, der Fehler auslöst
    Task.Factory.StartNew(() =>
    {
        Thread.Sleep(5000);
        tcs1.SetException(new InvalidOperationException("Simulierter 1. Fehler"));
        Thread.Sleep(2000);
        tcs1.SetException(new InvalidOperationException("Simulierter 2. Fehler"));
    });

     

    Bei der Ausführung kommt die Fehlermeldung:

    ... weil die Ausführung nach der 1. Exception nicht abgebrochen wird.

    Wie kann man dies erreichen?

    • Bearbeitet perlfred Dienstag, 13. Februar 2018 07:13
    Montag, 12. Februar 2018 13:59