Поделиться через


Закладки

Закладки — это механизм, позволяющий активности пассивно ожидать входящей информации без удержания на потоке рабочего процесса. Когда активность сигнализирует о том, что она ожидает стимула, она может создать закладку. Это означает, что выполнение действия не должно считаться завершенным, даже если текущий метод выполнения (который создал Bookmark) возвращается.

Основы закладки

Bookmark представляет точку, в которой можно возобновить исполнение (и через которую можно доставлять входные данные) в экземпляре рабочего процесса. Как правило, Bookmark получает имя, а внешний код (узла или расширения) отвечает за возобновление работы закладки с соответствующими данными. После возобновления выполнения рабочего процесса среда выполнения планирует делегата, связанного с этим Bookmark во время его создания.

Параметры закладки

Класс BookmarkOptions задает тип создаваемого Bookmark объекта. Возможные взаимоисключающие значения: None, MultipleResumeи NonBlocking. Используйте значение 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 возвращает значение перечисления, указывающее результаты запроса на возобновление закладки. Возможные возвращаемые значения: Successи NotReadyNotFound. Хосты и расширения могут использовать это значение, чтобы определить, как продолжить.