Windows Workflow Foundation の例外

ワークフローは、TryCatch アクティビティを使用して、ワークフローの実行中に発生した例外を処理することができます。 これらの例外は、処理することも可能ですが、Rethrow アクティビティを使用して再スローすることもできます。 Finally セクションのアクティビティは、Try セクションまたは Catches セクションが完了したときに実行されます。 また、WorkflowApplication インスタンスによってホストされるワークフローは OnUnhandledException イベント ハンドラーを使用して、TryCatch アクティビティで処理されない例外を処理することができます。

例外の原因

ワークフローでは、例外は、次の方法で生成されます。

  • TransactionScope でのトランザクションのタイムアウト

  • Throw アクティビティを使用してワークフローからスローされた明示的な例外

  • アクティビティからスローされた .NET Framework 4.6.1 例外。

  • ワークフローで使用されているライブラリ、コンポーネント、サービスなどの外部コードからスローされた例外

例外処理

アクティビティからスローされた例外が処理されない場合、既定の動作では、ワークフロー インスタンスが終了します。 カスタムの OnUnhandledException ハンドラーが存在する場合、このハンドラーで既定の動作をオーバーライドできます。 このハンドラーがあると、ワークフロー ホストの作成者は、カスタムのログ記録、ワークフローの中止、ワークフローのキャンセル、ワークフローの終了などの適切な処理を実行できます。 ワークフローが処理されない例外を発生する場合、OnUnhandledException ハンドラーが呼び出されます。 OnUnhandledException から戻された 3 つの可能なアクションがあり、これによりワークフローの最終結果が決定されます。

  • キャンセル - キャンセルされたワークフロー インスタンスは分岐実行の通常終了です。 キャンセルの動作をモデル化できます (たとえば、CancellationScope アクティビティを使用して)。 完了済みハンドラーはキャンセル プロセスが完了したときに呼び出されます。 取り消されたワーク フローはキャンセル状態にあります。

  • 終了 - 終了したワークフロー インスタンスは再開または再起動できません。 これにより完了イベントがトリガーされ、中断されたという理由の例外を提供できます。 終了したハンドラーはキャンセル プロセスが終了したときに呼び出されます。 終了したワークフローは失敗状態です。

  • 中止 - 永続的な構成をした場合にのみ、中止されたワークフロー インスタンスを再開できます。 永続化がない場合、ワークフローは再開できません。 ワークフローが中止したポイントで、最後の永続性ポイントが失われるため (メモリ内で)、どの作業も終了します。 中止されたワーク フローに対して、中止プロセスが完了したときの例外を使用して、中止されたハンドラーが呼び出されます。 しかし、キャンセルおよび終了と異なり、完了ハンドラーは呼び出されません。 中止されたワーク フローが中断状態にあります。

次の例では、例外をスローするワークフローを呼び出しています。 ワークフローで例外が処理されないため、OnUnhandledException ハンドラーが呼び出されます。 例外に関する情報を提供するために WorkflowApplicationUnhandledExceptionEventArgs が調査され、ワークフローは終了します。

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

TryCatch アクティビティでの例外処理

ワークフロー内部での例外処理は、TryCatch アクティビティで実行されます。 TryCatch アクティビティには、それぞれが特定の Exception 型に関連付けられている Catch アクティビティの Catches コレクションがあります。 Try アクティビティの TryCatch セクションに含まれているアクティビティからスローされた例外が、Catch<TException> コレクションの Catches アクティビティの例外に一致する場合、スローされた例外が処理されます。 例外が明示的に再スローされるか、新しい例外がスローされた場合、この例外は親アクティビティに渡されます。 次のコード例は、TryCatch セクションで ApplicationException アクティビティからスローされた Try を処理する Throw アクティビティを示しています。 例外のメッセージが Catch<TException> アクティビティによってコンソールに書き込まれた後、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."
    }
};

Finally セクションのアクティビティは、Try セクションまたは Catches セクションが正常に完了したときに実行されます。 例外がスローされない場合 Try セクションは正常に完了し、例外がスローまたは再スローされない場合 Catches セクションは正常に完了します。 例外が TryTryCatch セクションでスローされ、Catch<TException> セクションの Catches で処理されないか、または Catches から再スローされる場合、Finally のアクティビティは以下のいずれかが発生しない限り実行されません。

例外処理と補正の比較

例外処理は、アクティビティの実行中に発生するという点で補正と異なります。 補正が発生するのは、アクティビティが正常に完了した後です。 例外処理では、アクティビティが例外を生成した後でクリーン アップを実行できます。また、補正処理では、前に完了したアクティビティの正常に完了した作業を元に戻すことが可能です。 詳細については、「補正」を参照してください。

関連項目