Windows Workflow Foundation-Ausnahmen

Die TryCatch-Aktivität kann zur Behandlung von Ausnahmen verwendet werden, die während der Ausführung eines Workflows ausgelöst werden. Diese Ausnahmen können behandelt oder mit der Rethrow-Aktivität erneut ausgelöst werden. Aktivitäten im Abschnitt Finally werden nach Abschluss des Abschnitts Try oder des Abschnitts Catches ausgeführt. Von einer WorkflowApplication-Instanz gehostete Workflows können auch den Ereignishandler OnUnhandledException verwenden, um Ausnahmen zu behandeln, die nicht von einer TryCatch-Aktivität behandelt werden.

Ursachen von Ausnahmen

In einem Workflow können Ausnahmen auf die folgenden Weisen generiert werden:

  • Ein Timeout von Transaktionen in TransactionScope.

  • Eine explizite vom Workflow mit der Throw-Aktivität ausgelöste Ausnahme.

  • Eine .NET Framework 4.6.1-Ausnahme, die von einer Aktivität ausgelöst wird.

  • Eine von externem Code ausgelöste Ausnahme, z. B. Bibliotheken, Komponenten oder Dienste, die im Workflow verwendet werden.

Behandeln von Ausnahmen

Wenn eine Ausnahme von einer Aktivität ausgelöst und nicht behandelt wird, ist das Beenden der Workflowinstanz das Standardverhalten. Wenn ein benutzerdefinierter OnUnhandledException-Handler vorhanden ist, kann dieser das Standardverhalten überschreiben. Mit diesem Handler kann der Autor des Workflowhosts die angemessene Behandlung bereitstellen, z. B. benutzerdefinierte Protokollierung, Abbruch des Workflows oder Beenden des Workflows. Wenn ein Workflow eine nicht behandelte Ausnahme auslöst, wird der OnUnhandledException-Handler aufgerufen. Es gibt drei mögliche Aktionen, die von OnUnhandledException zurückgegeben werden und das endgültige Ergebnis des Workflows bestimmen.

  • Cancel: Eine abgebrochene Workflowinstanz entspricht dem ordnungsgemäßen Beenden der Ausführung einer Verzweigung. Sie können das Abbruchverhalten anpassen (z. B. durch Verwendung einer CancellationScope-Aktivität). Der Completed-Handler wird aufgerufen, wenn der Abbruchprozess abgeschlossen wird. Ein abgebrochener Workflow befindet sich im Cancelled-Zustand.

  • Terminate: Eine beendete Workflowinstanz kann nicht fortgesetzt oder neu gestartet werden. Dadurch wird das Completed-Ereignis ausgelöst, in dem Sie eine Ausnahme als Grund für die Beendigung bereitstellen können. Der Terminated-Handler wird aufgerufen, wenn der Beendigungsprozess abgeschlossen wird. Ein beendeter Workflow befindet sich im Faulted-Zustand.

  • Abort: eine abgebrochene Workflowinstanz kann nur fortgesetzt werden, wenn sie für Persistenz konfiguriert wurde. Ohne Persistenz kann ein Workflow nicht fortgesetzt werden. An dem Punkt, an dem ein Workflow abgebrochen wird, gehen alle seit dem letzten Persistenzpunkt verarbeiteten Daten (im Arbeitsspeicher) verloren. Für einen abgebrochenen Workflow wird der Aborted-Handler unter Verwendung der Ausnahme als Grund ausgelöst, wenn der Abbruchprozess beendet wird. Im Gegensatz zum Cancelled- und Terminated-Handler wird der Completed-Handler jedoch nicht aufgerufen. Ein abgebrochener Workflow befindet sich in einem Aborted-Zustand.

Im folgenden Beispiel wird ein Workflow aufgerufen, der eine Ausnahme auslöst. Die Ausnahme wird vom Workflow nicht behandelt, und der OnUnhandledException-Handler wird aufgerufen. Die WorkflowApplicationUnhandledExceptionEventArgs werden überprüft, um Informationen zur Ausnahme bereitzustellen, und der Workflow wird beendet.

Activity wf = new Sequence
{
    Activities =
     {
         new WriteLine
         {
             Text = "Starting the workflow."
         },
         new Throw
        {
            Exception = new InArgument<Exception>((env) =>
                new ApplicationException("Something unexpected happened."))
        },
        new WriteLine
         {
             Text = "Ending the workflow."
         }
     }
};

WorkflowApplication wfApp = new WorkflowApplication(wf);

wfApp.OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e)
{
    // Display the unhandled exception.
    Console.WriteLine("OnUnhandledException in Workflow {0}\n{1}",
        e.InstanceId, e.UnhandledException.Message);

    Console.WriteLine("ExceptionSource: {0} - {1}",
        e.ExceptionSource.DisplayName, e.ExceptionSourceInstanceId);

    // Instruct the runtime to terminate the workflow.
    return UnhandledExceptionAction.Terminate;

    // Other choices are UnhandledExceptionAction.Abort and
    // UnhandledExceptionAction.Cancel
};

wfApp.Run();

Behandeln von Ausnahmen mit der TryCatch-Aktivität

Zur Behandlung von Ausnahmen innerhalb eines Workflows dient die TryCatch-Aktivität. Die TryCatch-Aktivität verfügt über eine Catches-Auflistung von Catch-Aktivitäten, von denen jede einzelne einem bestimmten Exception-Typ zugeordnet ist. Wenn die Ausnahme, die von einer Aktivität im Try-Abschnitt einer TryCatch-Aktivität ausgelöst wurde, der Ausnahme einer Catch<TException>-Aktivität in der Catches-Auflistung entspricht, wird die Ausnahme behandelt. Wenn die Ausnahme explizit erneut ausgelöst wird oder eine neue Ausnahme ausgelöst wird, erfolgt die Übergabe dieser Ausnahme an die übergeordnete Aktivität. Das folgende Codebeispiel zeigt eine TryCatch-Aktivität, mit der eine ApplicationException-Ausnahme behandelt wird, die im Try-Abschnitt von einer Throw-Aktivität ausgelöst wurde. Die Meldung der Ausnahme wird von der Catch<TException>-Aktivität auf der Konsole ausgegeben. Anschließend wird eine Meldung im Finally-Abschnitt auf der Konsole ausgegeben.

DelegateInArgument<ApplicationException> ex = new DelegateInArgument<ApplicationException>()
{
    Name = "ex"
};

Activity wf = new TryCatch
{
    Try = new Throw()
    {
        Exception = new InArgument<Exception>((env) => new ApplicationException("An ApplicationException was thrown."))
    },
    Catches =
    {
        new Catch<ApplicationException>
        {
            Action = new ActivityAction<ApplicationException>
            {
                Argument = ex,
                Handler = new WriteLine()
                {
                    Text = new InArgument<string>((env) => ex.Get(env).Message)
                }
            }
        }
    },
    Finally = new WriteLine()
    {
        Text = "Executing in Finally."
    }
};

Die Aktivitäten im Finally-Abschnitt werden ausgeführt, wenn entweder der Try-Abschnitt oder der Catches-Abschnitt erfolgreich ausgeführt wurde. Der Try-Abschnitt wird erfolgreich abgeschlossen, sofern er keine Ausnahmen auslöst, und der Catches-Abschnitt wird erfolgreich abgeschlossen, wenn er keine Ausnahmen auslöst oder erneut auslöst. Wenn im Try-Abschnitt von TryCatch eine Ausnahme ausgelöst und nicht von einem Catch<TException> im Catches-Abschnitt behandelt wird oder durch Catches erneut ausgelöst wird, werden die Aktivitäten in Finally erst ausgeführt, nachdem eines der folgenden Ereignisse eintritt.

Ausnahmebehandlung und Kompensierung

Der Unterschied zwischen Ausnahmebehandlung und Kompensierung besteht darin, dass die Ausnahmebehandlung während der Ausführung einer Aktivität erfolgt. Die Kompensierung erfolgt, nachdem eine Aktivität erfolgreich abgeschlossen wurde. Die Ausnahmebehandlung bietet eine Möglichkeit, nach dem Auslösen der Ausnahme durch die Aktivität eine Bereinigung durchzuführen. Die Kompensierung dagegen stellt einen Mechanismus bereit, mit dem die erfolgreich abgeschlossene Arbeit einer zuvor abgeschlossenen Aktivität rückgängig gemacht werden kann. Weitere Informationen finden Sie unter Kompensierung.

Siehe auch