书签

书签是一种机制,使活动能够被动地等待输入,而无需保留工作流线程。 当活动指示它正在等待刺激时,它可以创建书签。 这向运行时表明,即使当前正在执行的方法(已创建 Bookmark)返回,此活动的执行也不应被视为完成。

书签基础知识

在工作流实例中,Bookmark 表示一个可以恢复执行的点(并通过该点传递输入)。 通常,Bookmark 会被赋予一个名称,然后由外部(如主机或扩展程序)的代码负责用相关数据恢复书签。 继续 Bookmark 后,工作流运行时会安排与其创建时的 BookmarkCallback 关联的 Bookmark 委托。

书签选项

"BookmarkOptions 类指定了创建的 Bookmark 类型。" 可能的非互斥值是 NoneMultipleResumeNonBlocking。 创建预期只继续一次的 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 活动时,该活动创建一个名为 BookmarkUserName,然后等待书签继续。 宿主收集所需的数据,然后继续 Bookmark。 工作流恢复后,会显示名称,然后完成。 请注意,恢复书签时不需要同步代码。 Bookmark只能在工作流空闲时恢复,如果工作流不空闲,对ResumeBookmark的调用会阻塞,直到工作流变为空闲。

书签继续结果

ResumeBookmark 返回一个 BookmarkResumptionResult 枚举值,指示书签恢复请求的结果。 可能的返回值为 SuccessNotReady以及 NotFound。 主机和扩展可以使用此值来确定如何继续。