Как запустить рабочий процесс
Данный раздел относится к версии Windows Workflow Foundation 4.
Этот раздел продолжает руководство «Приступая к работе» для Windows Workflow Foundation и указывает порядок выполнения рабочего процесса, описанного в предыдущем руководстве Как создать рабочий процесс.
Примечание |
---|
Каждый раздел в учебнике «Приступая к работе» построен на основе предыдущих разделов. Для изучения этого раздела необходимо сначала пройти руководства Как создать действие и Как создать рабочий процесс. |
Открытие проекта узла рабочего процесса
Откройте решение из предыдущего раздела Как создать рабочий процесс в среде Visual Studio 2010.
В Solution Explorer дважды щелкните Program.cs или Module1.vb для вывода кода.
Совет. Если окно Обозреватель решений не отображается, в меню Вид выберите пункт Обозреватель решений. Поскольку этот проект был создан с помощью шаблона Консольное приложение рабочего процесса, Program.cs или Module1.vb содержит следующий базовый код размещения рабочего процесса.
WorkflowInvoker.Invoke(New Workflow1())
WorkflowInvoker.Invoke(new Workflow1());
Этот созданный код размещения использует класс WorkflowInvoker. Класс WorkflowInvoker обеспечивает простой способ вызова рабочего процесса аналогично вызову метода и может использоваться только для рабочих процессов, не использующих сохраняемость. WorkflowApplication предоставляет улучшенную модель выполнения рабочих процессов, которая включает уведомления о событиях жизненного цикла, управление выполнением, возобновления закладок и сохраняемость. В этом примере используются закладки, а для размещения рабочего процесса используется WorkflowApplication. Добавьте инструкцию using или Imports в начало файла Program.cs или Module1.vb после существующих инструкций 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, подписывается на три события из жизненного цикла рабочего процесса, начинает рабочий процесс вызовом Run, а затем ждет завершения рабочего процесса. После завершения рабочего процесса устанавливается AutoResetEvent и ведущее приложение завершает работу.
Настройка входных аргументов рабочего процесса
Добавьте следующую инструкцию в начало файла Program.cs или Module1.vb после существующих инструкций using или Imports.
Imports System.Collections.Generic
using System.Collections.Generic;
Замените строку кода, создающую новое 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
. Ключи в словаре входных данных соответствуют входным аргументам в корневом действии рабочего процесса. ПараметрMaxNumber
используется рабочим процессом для определения верхней границы для созданного случайного числа.
Извлечение выходных аргументов рабочего процесса
Модифицируйте обработчик 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(); };
Возобновление закладки
Добавьте следующий код в начало метода
Main
сразу после существующего объявления AutoResetEvent.Dim idleEvent As New AutoResetEvent(False)
AutoResetEvent idleEvent = new AutoResetEvent(false);
Добавьте следующий обработчик Idle сразу после трех существующих обработчиков жизненного цикла процесса в
Main
.wfApp.Idle = _ Sub(e As WorkflowApplicationIdleEventArgs) idleEvent.Set() End Sub
wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e) { idleEvent.Set(); };
Каждый раз, когда рабочий процесс переходит в неактивный режим в ожидании следующего предположения, вызывается этот обработчик и устанавливается
idleAction
AutoResetEvent. Код на следующем этапе используетidleEvent
иsyncEvent
, чтобы определить, ждет рабочий процесс следующего предположения или он завершился.Примечание В этом примере ведущее приложение использует события автоматического сброса в обработчиках Completed и Idle, чтобы синхронизировать ведущее приложение с ходом выполнения рабочего процесса. Устанавливать блокировку и ждать неактивности рабочего процесса перед возобновлением закладки не обязательно, но в этом примере требуются события синхронизации, чтобы узел знал, завершен ли рабочий процесс, или он ждет дальнейшего ввода данных от пользователя с помощью Bookmark. Дополнительные сведения см. в разделе Закладки. Удалите вызов 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); } } }
Построение и запуск приложения
В Обозревателе решений щелкните правой кнопкой мыши WorkflowConsoleApplication1 и выберите команду Установить как запускаемый проект.
Нажмите сочетание клавиш 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);
}
}
}
}
См. также
Задачи
Как создать рабочий процесс
Как создать и запустить длительно выполняющийся рабочий процесс
Справочник
Другие ресурсы
Программирование в Windows Workflow Foundation
Учебник по началу работы
Ожидание входных данных в рабочем процессе
Размещение рабочих процессов