次の方法で共有


ワークフローを実行する方法

このトピックの内容は、Windows Workflow Foundation 4 に該当します。

このトピックでは、Windows Workflow Foundation 概要チュートリアルの続きと、前の「ワークフローを作成する方法」トピックで定義したワークフローを実行する方法について説明します。

Dd489463.note(ja-jp,VS.100).gif注 :
チュートリアル入門の各トピックは、前のトピックに応じて異なります。このトピックを完了する前に、「アクティビティを作成する方法」および「ワークフローを作成する方法」を完了する必要があります。

ワークフロー ホスト プロジェクトを開くには

  1. Visual Studio 2010 を使用して、前の「ワークフローを作成する方法」トピックからソリューションを開きます。

  2. ソリューション エクスプローラーで、Program.cs または Module1.vb をダブルクリックしてコードを表示します。

    Dd489463.Tip(ja-jp,VS.100).gifヒント :
    ソリューション エクスプローラー ウィンドウが表示されない場合は、[表示] メニューの [ソリューション エクスプローラー] をクリックします。

    このプロジェクトはワークフロー コンソール アプリケーション テンプレートを使用して作成されたため、Program.cs または Module1.vb には次のようなワークフローの基本的なホスティング コードが含まれます。

    WorkflowInvoker.Invoke(New Workflow1())
    
    WorkflowInvoker.Invoke(new Workflow1());
    

    この生成されたホスティング コードでは WorkflowInvoker を使用します。WorkflowInvoker はメソッド呼び出しのようにワークフローを呼び出す簡単な方法を提供し、永続化を使用しないワークフローのみに使用できます。WorkflowApplication は、ライフサイクル イベントの通知、実行制御、ブックマークの再開、および永続化など、ワークフローを実行するための豊富なモデルを提供します。次の例ではブックマークを使用し、ワークフローのホスティングには WorkflowApplication を使用します。Program.cs または Module1.vb の先頭にある既存の using ステートメントまたは Imports ステートメントの下に、次の using ステートメントまたは Imports ステートメントを追加します。

    Imports System.Threading
    
    using System.Threading;
    

    WorkflowInvoker を使用するコード行を次の WorkflowApplication の基本的なホスティング コードに置き換えます。このサンプル ホスティング コードでは、ワークフローをホストして呼び出すための基本的な手順を示します。ただし、このトピックのワークフローを正しく実行するための機能はまだありません。次の手順では、アプリケーションが完了するまでにこの基本的なコードを変更して機能を追加します。

    Dim syncEvent As New AutoResetEvent(False)
    
    Dim wfApp As New WorkflowApplication(New Workflow1())
    
    wfApp.Completed = _
        Sub(e As WorkflowApplicationCompletedEventArgs)
            syncEvent.Set()
        End Sub
    
    wfApp.Aborted = _
        Sub(e As WorkflowApplicationAbortedEventArgs)
            Console.WriteLine(e.Reason)
            syncEvent.Set()
        End Sub
    
    wfApp.OnUnhandledException = _
        Function(e As WorkflowApplicationUnhandledExceptionEventArgs)
            Console.WriteLine(e.UnhandledException)
            Return UnhandledExceptionAction.Terminate
        End Function
    
    wfApp.Run()
    
    syncEvent.WaitOne()
    
    AutoResetEvent syncEvent = new AutoResetEvent(false);
    
    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1());
    
    wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
    {
        syncEvent.Set();
    };
    
    wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
    {
        Console.WriteLine(e.Reason);
        syncEvent.Set();
    };
    
    wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
    {
        Console.WriteLine(e.UnhandledException.ToString());
        return UnhandledExceptionAction.Terminate;
    };
    
    wfApp.Run();
    
    syncEvent.WaitOne();
    

    このコードでは WorkflowApplication を作成し、3 つのワークフローのライフサイクル イベントにサブスクライブし、Run を呼び出してワークフローを開始し、そのワークフローが完了するまで待機します。ワークフローが完了すると AutoResetEvent が設定され、ホスト アプリケーションが完了します。

ワークフローの入力引数を設定するには

  1. Program.cs または Module1.vb の先頭にある既存の using ステートメントまたは Imports ステートメントの下に、次のステートメントを追加します。

    Imports System.Collections.Generic
    
    using System.Collections.Generic;
    
  2. 新しい WorkflowApplication を作成するコード行を、作成時にワークフローにパラメーターの辞書を作成して渡す次のコードに置き換えます。

    Dim inputs As New Dictionary(Of String, Object)
    inputs.Add("MaxNumber", 100)
    
    Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)
    
    var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } };
    
    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1(), inputs);
    

    この辞書には、MaxNumber というキーを持つ 1 つの要素が含まれます。入力辞書のキーは、ワークフローのルート アクティビティの入力引数に対応します。MaxNumber は、ワークフローがランダムに生成された数値の上限を判断する場合に使用されます。

ワークフローの出力引数を取得するには

  1. Completed ハンドラーを変更して、ワークフローが使用する順番の数を取得して表示します。

    wfApp.Completed = _
        Sub(e As WorkflowApplicationCompletedEventArgs)
            Dim Turns As Integer = Convert.ToInt32(e.Outputs("Turns"))
            Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns)
    
            syncEvent.Set()
        End Sub
    
    wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
    {
        int Turns = Convert.ToInt32(e.Outputs["Turns"]);
        Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns);
    
        syncEvent.Set();
    };
    

ブックマークを再開するには

  1. Main メソッドの上部にある既存の AutoResetEvent 宣言の直後に、次のコードを追加します。

    Dim idleEvent As New AutoResetEvent(False)
    
    AutoResetEvent idleEvent = new AutoResetEvent(false);
    
  2. Main にある既存の 3 つのワークフロー ライフサイクル ハンドラーの直後に、次の Idle ハンドラーを追加します。

    wfApp.Idle = _
        Sub(e As WorkflowApplicationIdleEventArgs)
            idleEvent.Set()
        End Sub
    
    wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
    {
        idleEvent.Set();
    };
    

    このハンドラーは、次の推定値を待機してワークフローがアイドル状態になるたびに呼び出され、idleAction AutoResetEvent が設定されます。次の手順のコードでは、idleEventsyncEvent を使用して、ワークフローが次の推定値を待機しているのか、完了しているのかを判断します。

    Dd489463.note(ja-jp,VS.100).gif注 :
    この例では、ホスト アプリケーションは Completed および Idle ハンドラーの自動リセット イベントを使用して、ホスト アプリケーションとワークフローの進行状況を同期させます。ブックマークを再開する前にワークフローがアイドル状態になるのをブロックして待機する必要はありませんが、この例では同期イベントが必要であるため、ホストはワークフローが完了しているのか、さらにユーザーの入力を待っているのかを Bookmark を使用して把握します。詳細については、次のトピックを参照してください。ブックマーク.

  3. WaitOne への呼び出しを削除して、ユーザーからの入力を収集して Bookmark を再開するためのコードに置き換えます。

    次のコード行を削除します。

    syncEvent.WaitOne()
    
    syncEvent.WaitOne();
    

    これを次の例に置き換えます。

    ' Loop until the workflow completes.
    Dim waitHandles As WaitHandle() = New WaitHandle() {syncEvent, idleEvent}
    Do While WaitHandle.WaitAny(waitHandles) <> 0
        'Gather the user input and resume the bookmark.
        Dim validEntry As Boolean = False
        Do While validEntry = False
            Dim Guess As Integer
            If Int32.TryParse(Console.ReadLine(), Guess) = False Then
                Console.WriteLine("Please enter an integer.")
            Else
                validEntry = True
                wfApp.ResumeBookmark("EnterGuess", Guess)
            End If
        Loop
    Loop
    
    // Loop until the workflow completes.
    WaitHandle[] handles = new WaitHandle[] { syncEvent, idleEvent };
    while (WaitHandle.WaitAny(handles) != 0)
    {
        // Gather the user input and resume the bookmark.
        bool validEntry = false;
        while (!validEntry)
        {
            int Guess;
            if (!Int32.TryParse(Console.ReadLine(), out Guess))
            {
                Console.WriteLine("Please enter an integer.");
            }
            else
            {
                validEntry = true;
                wfApp.ResumeBookmark("EnterGuess", Guess);
            }
        }
    }
    

アプリケーションをビルドして実行するには

  1. ソリューション エクスプローラーWorkflowConsoleApplication1 を右クリックして [スタートアップ プロジェクトに設定] を選択します。

  2. Ctrl キーを押しながら F5 キーを押してアプリケーションをビルドし、実行します。できるだけ早い順番の数を推測します。

    ワークフロー アプリケーションに永続化を追加する方法については、次のトピック「長時間にわたって実行されるワークフローを作成して実行する方法」を参照してください。

次の例では、Main メソッドの完全なコードの一覧を示します。

Sub Main()
    Dim syncEvent As New AutoResetEvent(False)
    Dim idleEvent As New AutoResetEvent(False)

    Dim inputs As New Dictionary(Of String, Object)
    inputs.Add("MaxNumber", 100)

    Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)

    wfApp.Completed = _
        Sub(e As WorkflowApplicationCompletedEventArgs)
            Dim Turns As Integer = Convert.ToInt32(e.Outputs("Turns"))
            Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns)

            syncEvent.Set()
        End Sub

    wfApp.Aborted = _
        Sub(e As WorkflowApplicationAbortedEventArgs)
            Console.WriteLine(e.Reason)
            syncEvent.Set()
        End Sub

    wfApp.OnUnhandledException = _
        Function(e As WorkflowApplicationUnhandledExceptionEventArgs)
            Console.WriteLine(e.UnhandledException)
            Return UnhandledExceptionAction.Terminate
        End Function

    wfApp.Idle = _
        Sub(e As WorkflowApplicationIdleEventArgs)
            idleEvent.Set()
        End Sub

    wfApp.Run()

    ' Loop until the workflow completes.
    Dim waitHandles As WaitHandle() = New WaitHandle() {syncEvent, idleEvent}
    Do While WaitHandle.WaitAny(waitHandles) <> 0
        'Gather the user input and resume the bookmark.
        Dim validEntry As Boolean = False
        Do While validEntry = False
            Dim Guess As Integer
            If Int32.TryParse(Console.ReadLine(), Guess) = False Then
                Console.WriteLine("Please enter an integer.")
            Else
                validEntry = True
                wfApp.ResumeBookmark("EnterGuess", Guess)
            End If
        Loop
    Loop
End Sub
static void Main(string[] args)
{
    AutoResetEvent syncEvent = new AutoResetEvent(false);
    AutoResetEvent idleEvent = new AutoResetEvent(false);

    var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } };

    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1(), inputs);

    wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
    {
        int Turns = Convert.ToInt32(e.Outputs["Turns"]);
        Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns);

        syncEvent.Set();
    };

    wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
    {
        Console.WriteLine(e.Reason);
        syncEvent.Set();
    };

    wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
    {
        Console.WriteLine(e.UnhandledException.ToString());
        return UnhandledExceptionAction.Terminate;
    };

    wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
    {
        idleEvent.Set();
    };

    wfApp.Run();

    // Loop until the workflow completes.
    WaitHandle[] handles = new WaitHandle[] { syncEvent, idleEvent };
    while (WaitHandle.WaitAny(handles) != 0)
    {
        // Gather the user input and resume the bookmark.
        bool validEntry = false;
        while (!validEntry)
        {
            int Guess;
            if (!Int32.TryParse(Console.ReadLine(), out Guess))
            {
                Console.WriteLine("Please enter an integer.");
            }
            else
            {
                validEntry = true;
                wfApp.ResumeBookmark("EnterGuess", Guess);
            }
        }
    }
}

参照

処理手順

ワークフローを作成する方法
長時間にわたって実行されるワークフローを作成して実行する方法

リファレンス

WorkflowApplication
Bookmark

その他のリソース

Windows Workflow Foundation プログラミングの新機能
チュートリアル入門
ワークフロー内での入力の待機
ワークフローのホスティング