次の方法で共有


Windows Workflow Foundation の例外

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

例外の原因

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

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

  • Throw アクティビティを使用してワークフローによってスローされる明示的な例外。

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

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

例外の処理

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

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

  • 終了 - 終了したワークフロー インスタンスを再開または再起動することはできません。 これにより、終了した理由として例外を指定できる Completed イベントがトリガーされます。 終了ハンドラーは、終了プロセスが完了したときに呼び出されます。 終了したワークフローは Faulted 状態です。

  • 中止 - 中止されたワークフロー インスタンスは、永続的に構成されている場合にのみ再開できます。 永続化がないと、ワークフローを再開できません。 ワークフローが中止された時点で、最後の永続化ポイント以降に実行された (メモリ内の) 作業はすべて失われます。 中止されたワークフローの場合、中止されたハンドラーは、中止プロセスが完了した理由として例外を使用して呼び出されます。 ただし、Cancelled と Terminated とは異なり、Completed ハンドラーは呼び出されません。 中止されたワークフローが中止状態です。

次の例では、例外をスローするワークフローを呼び出します。 例外はワークフローによって処理され、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 {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();

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

ワークフロー内での例外の処理は、TryCatch アクティビティで実行されます。 TryCatch アクティビティには、それぞれ特定の Exception の種類に関連付けられている Catch アクティビティの Catches コレクションがあります。 TryCatch アクティビティの Try セクションに含まれるアクティビティによってスローされた例外が、Catches コレクション内の Catch<TException> アクティビティの例外と一致する場合、例外が処理されます。 例外が明示的に再スローされるか、新しい例外がスローされた場合、この例外は親アクティビティに渡されます。 次のコード例は、Throw アクティビティによって Try セクションでスローされる ApplicationException を処理する TryCatch アクティビティを示しています。 例外のメッセージは、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 セクションは例外がスローされないか、そこから再スローされた場合に正常に完了します。 TryCatchTry セクションで例外がスローされ、Catches セクションの Catch<TException> によって処理されない場合、または Catchesから再スローされた場合、Finally 内のアクティビティは、次のいずれかが発生しない限り実行されません。

  • 例外は、その上位レベルの TryCatchから再スローされるかどうかに関係なく、ワークフロー内の上位レベルの TryCatch アクティビティによってキャッチされます。

  • 例外は、より高いレベルの TryCatchでは処理されず、ワークフローのルートをエスケープし、ワークフローは終了または中止の代わりにキャンセルするように構成されます。 WorkflowApplication を使用してホストされるワークフローは、OnUnhandledException を処理して Cancelを返すことで、これを構成できます。 OnUnhandledException の処理の例は、このトピックで既に説明しています。 ワークフロー サービスでは、WorkflowUnhandledExceptionBehavior を使用してこれを構成し、Cancelを指定できます。 WorkflowUnhandledExceptionBehaviorの構成例については、「ワークフロー サービス ホストの拡張 参照してください。

例外処理と補正

例外処理と補正の違いは、アクティビティの実行中に例外処理が発生することです。 補正は、アクティビティが正常に完了した後に発生します。 例外処理は、アクティビティが例外を発生した後にクリーンアップする機会を提供しますが、補正は、以前に完了したアクティビティの正常に完了した作業を元に戻すことができるメカニズムを提供します。 詳細については、「補正」を参照してください。

こちらもご覧ください