ブックマーク

ブックマークは、ワークフローのスレッド上に保持することなく、アクティビティが受動的に入力を待機できるようにする機構です。 アクティビティが働きかけを待機していることを示すときは、ブックマークを作成できます。 これは、現在実行中の (Bookmark を作成した) メソッドから返された場合でも、アクティビティの実行が完了していると見なさないことをランタイムに対して示します。

ブックマークの基本

Bookmark は、ワークフロー インスタンス内で実行を再開できるポイント (および入力を渡すことができるポイント) を表します。 通常、Bookmark には名前が付けられ、外部 (ホストまたは拡張) コードで、関連データを含むブックマークを再開する処理を実行します。 Bookmark を再開すると、ワークフロー ランタイムは、作成時に、その BookmarkCallback と関連付けられた Bookmark のデリゲートをスケジュールします。

ブックマークのオプション

BookmarkOptions クラスは、作成する Bookmark の種類を指定します。 互いに矛盾しない値として、NoneMultipleResume、および NonBlocking があります。 1 度のみ再開される想定の None を作成する場合、既定では Bookmark を使用します。 複数回再開できる MultipleResume を作成する場合は、Bookmark を使用します。 再開しない NonBlocking を作成する場合は、Bookmark を使用します。 既定の BookmarkOptions を使用して作成されるブックマークとは異なり、NonBlocking ブックマークはアクティビティの完了を妨げません。

ブックマークの再開

ブックマークは、ワークフロー以外のコードから、ResumeBookmark オーバーロードのいずれかを使用して再開できます。 この例では、ReadLine アクティビティが作成されます。 実行されると、ReadLine アクティビティは Bookmark を作成し、コールバックを登録してから、Bookmark が再開されるのを待機します。 再開されると、ReadLine アクティビティは Bookmark と一緒に渡されたデータを Result 引数に代入します。

public sealed class ReadLine : NativeActivity<string>  
{  
    [RequiredArgument]  
    public  InArgument<string> BookmarkName { get; set; }  
  
    protected override void Execute(NativeActivityContext context)  
    {  
        // Create a Bookmark and wait for it to be resumed.  
        context.CreateBookmark(BookmarkName.Get(context),
            new BookmarkCallback(OnResumeBookmark));  
    }  
  
    // NativeActivity derived activities that do asynchronous operations by calling
    // one of the CreateBookmark overloads defined on System.Activities.NativeActivityContext
    // must override the CanInduceIdle property and return true.  
    protected override bool CanInduceIdle  
    {  
        get { return true; }  
    }  
  
    public void OnResumeBookmark(NativeActivityContext context, Bookmark bookmark, object obj)  
    {  
        // When the Bookmark is resumed, assign its value to  
        // the Result argument.  
        Result.Set(context, (string)obj);  
    }  
}  

次の例では、ReadLine アクティビティを使用してユーザー名を収集し、それをコンソール ウィンドウに表示するワークフローを作成します。 ホスト アプリケーションは入力を収集する実際の作業を実行し、Bookmark を再開することでワークフローに渡します。

Variable<string> name = new Variable<string>  
{  
    Name = "name"  
};  
  
Activity wf = new Sequence  
{  
    Variables =  
    {  
        name  
    },  
    Activities =  
    {  
        new WriteLine()  
        {  
            Text = "What is your name?"  
        },  
        new ReadLine()  
        {  
            BookmarkName = "UserName",  
            Result = name  
        },  
        new WriteLine()  
        {  
            Text = new InArgument<string>((env) => "Hello, " + name.Get(env))  
        }  
    }  
};  
  
AutoResetEvent syncEvent = new AutoResetEvent(false);  
  
// Create the WorkflowApplication using the desired  
// workflow definition.  
WorkflowApplication wfApp = new WorkflowApplication(wf);  
  
// Handle the desired lifecycle events.  
wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)  
{  
    // Signal the host that the workflow is complete.  
    syncEvent.Set();  
};  
  
// Start the workflow.  
wfApp.Run();  
  
// Collect the user's name and resume the bookmark.  
// Bookmark resumption only occurs when the workflow  
// is idle. If a call to ResumeBookmark is made and the workflow  
// is not idle, ResumeBookmark blocks until the workflow becomes  
// idle before resuming the bookmark.  
wfApp.ResumeBookmark("UserName", Console.ReadLine());  
  
// Wait for Completed to arrive and signal that  
// the workflow is complete.  
syncEvent.WaitOne();  

ReadLine アクティビティが実行されると、Bookmark という名前の UserName が作成され、ブックマークが再開されるのを待機します。 ホストは必要なデータを収集し、Bookmark を再開します。 ワークフローが再開されると名前が表示されて、完了します。 ブックマークの再開に関して、同期コードは必要ありません。 Bookmark を再開できるのは、ワークフローがアイドルの場合のみです。ワークフローがアイドルではない場合、ResumeBookmark を呼び出すと、ワークフローがアイドルになるまでブロックされます。

ブックマークの再開結果

ResumeBookmark は、ブックマークの再開要求の結果を示す BookmarkResumptionResult 列挙値を返します。 戻り値には SuccessNotReady、および NotFound があります。 ホストと拡張ではこの値を使用して処理の進め方を決定します。