Condividi tramite


Eccezioni di Windows Workflow Foundation

I flussi di lavoro possono usare l'attività TryCatch per gestire le eccezioni generate durante l'esecuzione di un flusso di lavoro. Queste eccezioni possono essere gestite oppure possono essere generate nuovamente usando l'attività Rethrow. Le attività nella sezione Finally vengono eseguite al termine della sezione Try o della sezione Catches. I flussi di lavoro ospitati da un'istanza di WorkflowApplication possono usare anche il gestore eventi OnUnhandledException per gestire le eccezioni non gestite da un'attività TryCatch.

Cause di eccezioni

In un flusso di lavoro è possibile generare eccezioni nei modi seguenti:

  • Timeout delle transazioni in TransactionScope.

  • Eccezione esplicita generata dal flusso di lavoro utilizzando l'attività Throw.

  • Eccezione di .NET Framework 4.6.1 generata da un'attività.

  • Eccezione generata da codice esterno, ad esempio librerie, componenti o servizi usati nel flusso di lavoro.

Gestione delle eccezioni

Se un'eccezione viene generata da un'attività e non gestita, il comportamento predefinito consiste nell'terminare l'istanza del flusso di lavoro. Se è presente un gestore OnUnhandledException personalizzato, può eseguire l'override di questo comportamento predefinito. Questo gestore consente all'autore dell'host del flusso di lavoro di fornire la gestione appropriata, ad esempio la registrazione personalizzata, l'interruzione del flusso di lavoro, l'annullamento del flusso di lavoro o la chiusura del flusso di lavoro. Se un flusso di lavoro genera un'eccezione non gestita, viene richiamato il gestore OnUnhandledException. Esistono tre possibili azioni restituite da OnUnhandledException che determinano il risultato finale del flusso di lavoro.

  • Annulla: un'istanza del flusso di lavoro annullata è un'uscita normale di un'esecuzione del ramo. È possibile modellare il comportamento di annullamento, ad esempio usando un'attività CancellationScope. Il gestore Completato viene richiamato al termine del processo di annullamento. Un flusso di lavoro annullato si trova nello stato Annullato.

  • Termina: non è possibile riprendere o riavviare un'istanza del flusso di lavoro terminata. In questo modo viene attivato l'evento Completed in cui è possibile fornire un'eccezione come motivo per cui è stato terminato. Il gestore Terminato viene richiamato al termine del processo di terminazione. Un flusso di lavoro terminato si trova nello stato Faulted.

  • l'interruzione: è possibile riprendere un'istanza del flusso di lavoro interrotta solo se è stata configurata per essere persistente. Senza persistenza, non è possibile riprendere un flusso di lavoro. Nel momento in cui un flusso di lavoro viene interrotto, tutte le operazioni eseguite (in memoria) dall'ultimo punto di persistenza andranno perse. Per un flusso di lavoro interrotto, il gestore interrotto viene richiamato utilizzando l'eccezione come motivo per il completamento del processo di interruzione. Tuttavia, a differenza di Cancelled e Terminate, il gestore Completato non viene richiamato. Un flusso di lavoro interrotto si trova in uno stato interrotto.

Nell'esempio seguente viene richiamato un flusso di lavoro che genera un'eccezione. L'eccezione non viene gestita dal flusso di lavoro e viene richiamato il gestore OnUnhandledException. Il WorkflowApplicationUnhandledExceptionEventArgs viene controllato per fornire informazioni sull'eccezione e il flusso di lavoro viene terminato.

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 {e.InstanceId}\n{e.UnhandledException.Message}");

    Console.WriteLine($"ExceptionSource: {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();

Gestione delle eccezioni con l'attività TryCatch

La gestione delle eccezioni all'interno di un flusso di lavoro viene eseguita con l'attività TryCatch. L'attività TryCatch include una raccolta Catches di attività Catch associate a un tipo di Exception specifico. Se l'eccezione generata da un'attività contenuta nella sezione Try di un'attività TryCatch corrisponde all'eccezione di un'attività Catch<TException> nella raccolta Catches, l'eccezione viene gestita. Se l'eccezione viene generata nuovamente in modo esplicito o viene generata una nuova eccezione, questa eccezione passa all'attività padre. Nell'esempio di codice seguente viene illustrata un'attività di TryCatch che gestisce un ApplicationException generato nella sezione Try da un'attività Throw. Il messaggio dell'eccezione viene scritto nella console dall'attività Catch<TException> e quindi viene scritto un messaggio nella console nella sezione Finally.

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."
    }
};

Le attività nella sezione Finally vengono eseguite quando la sezione Try o la sezione Catches viene completata correttamente. La sezione Try viene completata correttamente se non viene generata alcuna eccezione e la sezione Catches viene completata correttamente se non viene generata alcuna eccezione o viene generata nuovamente. Se viene generata un'eccezione nella sezione Try di un TryCatch e non viene gestita da un Catch<TException> nella sezione Catches oppure viene nuovamente generata dalla Catches, le attività nell'Finally non verranno eseguite a meno che non si verifichi una delle condizioni seguenti.

  • L'eccezione viene rilevata da un'attività di TryCatch di livello superiore nel flusso di lavoro, indipendentemente dal fatto che venga nuovamente generata da tale livello superiore TryCatch.

  • L'eccezione non viene gestita da un livello superiore TryCatch, esegue l'escape della radice del flusso di lavoro e il flusso di lavoro è configurato per annullare anziché terminare o interrompere. I flussi di lavoro ospitati tramite WorkflowApplication possono configurare questa operazione gestendo OnUnhandledException e restituendo Cancel. Un esempio di gestione delle OnUnhandledException viene fornito in precedenza in questo argomento. I servizi flusso di lavoro possono configurare questa funzionalità usando WorkflowUnhandledExceptionBehavior e specificando Cancel. Per un esempio di configurazione di WorkflowUnhandledExceptionBehavior, vedere estendibilità dell'host del servizio flusso di lavoro .

Gestione delle eccezioni e compensazione

La differenza tra la gestione delle eccezioni e la compensazione è che la gestione delle eccezioni si verifica durante l'esecuzione di un'attività. La compensazione si verifica dopo il completamento di un'attività. La gestione delle eccezioni consente di eseguire la pulizia dopo che l'attività genera l'eccezione, mentre la compensazione fornisce un meccanismo in base al quale è possibile annullare il lavoro completato correttamente di un'attività completata in precedenza. Per altre informazioni, vedere Compensazione.

Vedere anche