Instrukcje: Uruchamianie przepływu pracy
Ten temat jest kontynuacją samouczka Wprowadzenie do programu Windows Workflow Foundation i omówiono sposób tworzenia hosta przepływu pracy i uruchamiania przepływu pracy zdefiniowanego w poprzednim temacie Instrukcje: tworzenie przepływu pracy .
Uwaga
Każdy temat w samouczku Wprowadzenie zależy od poprzednich tematów. Aby ukończyć ten temat, należy najpierw wykonać czynności: Tworzenie działania i Instrukcje: Tworzenie przepływu pracy.
Aby utworzyć projekt hosta przepływu pracy
Otwórz rozwiązanie z poprzedniego tematu Porady: tworzenie tematu działania przy użyciu programu Visual Studio 2012.
Kliknij prawym przyciskiem myszy rozwiązanie WF45GettingStartedTutorial w Eksplorator rozwiązań i wybierz polecenie Dodaj nowy projekt.
Napiwek
Jeśli okno Eksplorator rozwiązań nie jest wyświetlane, wybierz pozycję Eksplorator rozwiązań z menu Widok.
W węźle Zainstalowany wybierz pozycję Visual C#, Workflow (lub Visual Basic, Workflow).
Uwaga
W zależności od tego, który język programowania jest skonfigurowany jako język podstawowy w programie Visual Studio, węzeł Visual C# lub Visual Basic może znajdować się w węźle Inne języki w węźle Zainstalowane .
Upewnij się, że program .NET Framework 4.5 został wybrany na liście rozwijanej Wersja programu .NET Framework. Wybierz pozycję Aplikacja konsoli przepływu pracy z listy Przepływ pracy . Wpisz
NumberGuessWorkflowHost
w polu Nazwa i kliknij przycisk OK. Spowoduje to utworzenie początkowej aplikacji przepływu pracy z podstawową obsługą hostingu przepływu pracy. Ten podstawowy kod hostingu jest modyfikowany i używany do uruchamiania aplikacji przepływu pracy.Kliknij prawym przyciskiem myszy nowo dodany projekt NumberGuessWorkflowHost w Eksplorator rozwiązań i wybierz polecenie Dodaj odwołanie. Wybierz pozycję Rozwiązanie z listy Dodaj odwołanie , zaznacz pole wyboru obok pozycji NumberGuessWorkflowActivities, a następnie kliknij przycisk OK.
Kliknij prawym przyciskiem myszy plik Workflow1.xaml w Eksplorator rozwiązań i wybierz polecenie Usuń. Kliknij przycisk OK , aby potwierdzić.
Aby zmodyfikować kod hostingu przepływu pracy
Kliknij dwukrotnie Program.cs lub Module1.vb w Eksplorator rozwiązań, aby wyświetlić kod.
Napiwek
Jeśli okno Eksplorator rozwiązań nie jest wyświetlane, wybierz pozycję Eksplorator rozwiązań z menu Widok.
Ponieważ ten projekt został utworzony przy użyciu szablonu aplikacja konsoli przepływu pracy, Program.cs lub Module1.vb zawiera następujący podstawowy kod hostingu przepływu pracy.
' Create and cache the workflow definition. Dim workflow1 As Activity = New Workflow1() WorkflowInvoker.Invoke(workflow1)
// Create and cache the workflow definition. Activity workflow1 = new Workflow1(); WorkflowInvoker.Invoke(workflow1);
Ten wygenerowany kod hostingu używa metody WorkflowInvoker. WorkflowInvoker Zapewnia prosty sposób wywoływania przepływu pracy tak, jakby był to wywołanie metody i może być używany tylko w przypadku przepływów pracy, które nie używają trwałości. WorkflowApplication Udostępnia bogatszy model wykonywania przepływów pracy, który obejmuje powiadomienia o zdarzeniach cyklu życia, kontroli wykonywania, wznowieniu zakładek i trwałości. W tym przykładzie użyto zakładek i WorkflowApplication użyto ich do hostowania przepływu pracy. Dodaj następującą
using
instrukcję lub Import w górnej części Program.cs lub Module1.vb poniżej istniejących instrukcji using lub Import .Imports NumberGuessWorkflowActivities Imports System.Threading
using NumberGuessWorkflowActivities; using System.Threading;
Zastąp wiersze kodu, które używają WorkflowInvoker następującego podstawowego WorkflowApplication kodu hostingu. Ten przykładowy kod hostingu przedstawia podstawowe kroki hostowania i wywoływania przepływu pracy, ale nie zawiera jeszcze funkcji pomyślnego uruchomienia przepływu pracy z tego tematu. W poniższych krokach ten podstawowy kod jest modyfikowany, a dodatkowe funkcje są dodawane do momentu ukończenia aplikacji.
Uwaga
W tych przykładach należy zastąpić
Workflow1
element ,SequentialNumberGuessWorkflow
lubStateMachineNumberGuessWorkflow
, w zależności od tego, który przepływ pracy został ukończony w poprzednim kroku Instrukcje: tworzenie przepływu pracy.FlowchartNumberGuessWorkflow
Jeśli nie zastąpiszWorkflow1
, podczas próby kompilacji lub uruchomienia przepływu pracy wystąpią błędy kompilacji.AutoResetEvent syncEvent = new AutoResetEvent(false); WorkflowApplication wfApp = new WorkflowApplication(_wf); 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();
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()
Ten kod tworzy element WorkflowApplication, subskrybuje trzy zdarzenia cyklu życia przepływu pracy, uruchamia przepływ pracy z wywołaniem Runmetody , a następnie czeka na zakończenie przepływu pracy. Po zakończeniu przepływu pracy zostanie ustawiona AutoResetEvent wartość , a aplikacja hosta zostanie ukończona.
Aby ustawić argumenty wejściowe przepływu pracy
Dodaj następującą instrukcję w górnej części Program.cs lub Module1.vb poniżej istniejących
using
instrukcji lubImports
.Zastąp wiersz kodu, który tworzy nowy WorkflowApplication , następującym kodem, który tworzy i przekazuje słownik parametrów do przepływu pracy podczas jego tworzenia.
Uwaga
W tych przykładach zastąp ciąg
Workflow1
,SequentialNumberGuessWorkflow
lubStateMachineNumberGuessWorkflow
, w zależności od tego, który przepływ pracy został ukończony w poprzednim kroku Instrukcje: tworzenie przepływu pracy.FlowchartNumberGuessWorkflow
Jeśli nie zastąpiszWorkflow1
, podczas próby kompilacji lub uruchomienia przepływu pracy wystąpią błędy kompilacji.var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } }; WorkflowApplication wfApp = new(_wf, inputs) {
Dim inputs As New Dictionary(Of String, Object) inputs.Add("MaxNumber", 100) Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)
Ten słownik zawiera jeden element z kluczem
MaxNumber
. Klucze w słowniku wejściowym odpowiadają argumentom wejściowym w działaniu głównym przepływu pracy.MaxNumber
jest używany przez przepływ pracy do określenia górnej granicy dla losowo wygenerowanej liczby.
Aby pobrać argumenty wyjściowe przepływu pracy
Zmodyfikuj procedurę obsługi, Completed aby pobrać i wyświetlić liczbę zmian używanych przez przepływ pracy.
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.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
Aby wznowić zakładkę
Dodaj następujący kod w górnej części
Main
metody tuż po istniejącej AutoResetEvent deklaracji.AutoResetEvent idleEvent = new AutoResetEvent(false);
Dim idleEvent As New AutoResetEvent(False)
Dodaj następującą Idle procedurę obsługi tuż poniżej istniejących trzech procedur obsługi cyklu życia przepływu pracy w programie
Main
.Idle = delegate (WorkflowApplicationIdleEventArgs e) { idleEvent.Set(); } };
wfApp.Idle = Sub(e As WorkflowApplicationIdleEventArgs) idleEvent.Set() End Sub
Za każdym razem, gdy przepływ pracy stanie się w stanie bezczynności podczas następnego odgadnięcia, ta procedura obsługi jest wywoływana
idleAction
AutoResetEvent i ustawiana. Kod w poniższym kroku używaidleEvent
instrukcji isyncEvent
określa, czy przepływ pracy oczekuje na następne odgadnięcie, czy został ukończony.Uwaga
W tym przykładzie aplikacja hosta używa zdarzeń automatycznego resetowania w programach Completed obsługi i Idle w celu zsynchronizowania aplikacji hosta z postępem przepływu pracy. Nie jest konieczne blokowanie i oczekiwanie na bezczynność przepływu pracy przed wznowieniem zakładki, ale w tym przykładzie zdarzenia synchronizacji są wymagane, aby host wiedział, czy przepływ pracy został ukończony, czy oczekuje na więcej danych wejściowych użytkownika przy użyciu .Bookmark Aby uzyskać więcej informacji, zobacz Zakładki.
Usuń wywołanie metody
WaitOne
i zastąp go kodem, aby zebrać dane wejściowe od użytkownika i wznowić polecenie Bookmark.Usuń następujący wiersz kodu.
syncEvent.WaitOne();
syncEvent.WaitOne()
Zastąp go poniższym przykładem.
// 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) { if (!Int32.TryParse(Console.ReadLine(), out int Guess)) { Console.WriteLine("Please enter an integer."); } else { validEntry = true; wfApp.ResumeBookmark("EnterGuess", Guess); } } }
' 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
Aby skompilować i uruchomić aplikację
Kliknij prawym przyciskiem myszy pozycję NumberGuessWorkflowHost w Eksplorator rozwiązań i wybierz pozycję Ustaw jako projekt startowy.
Naciśnij CTRL+F5, aby skompilować i uruchomić aplikację. Spróbuj odgadnąć liczbę w jak najmniejszej liczbie zakrętów.
Aby wypróbować aplikację przy użyciu jednego z innych stylów przepływu pracy, zastąp element
Workflow1
w kodzie, który tworzy WorkflowApplication element ,FlowchartNumberGuessWorkflow
SequentialNumberGuessWorkflow
lubStateMachineNumberGuessWorkflow
, w zależności od tego, który styl przepływu pracy jest pożądany.var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } }; WorkflowApplication wfApp = new(_wf, inputs) {
Dim inputs As New Dictionary(Of String, Object) inputs.Add("MaxNumber", 100) Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)
Aby uzyskać instrukcje dotyczące dodawania trwałości do aplikacji przepływu pracy, zobacz następny temat : Tworzenie i uruchamianie długotrwałego przepływu pracy.
Przykład
Poniższy przykład to kompletna lista kodu dla Main
metody .
Uwaga
W tych przykładach zastąp ciąg Workflow1
, SequentialNumberGuessWorkflow
lub StateMachineNumberGuessWorkflow
, w zależności od tego, który przepływ pracy został ukończony w poprzednim kroku Instrukcje: tworzenie przepływu pracy.FlowchartNumberGuessWorkflow
Jeśli nie zastąpisz Workflow1
, podczas próby kompilacji lub uruchomienia przepływu pracy wystąpią błędy kompilacji.
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(_wf, inputs)
{
Completed = delegate (WorkflowApplicationCompletedEventArgs e)
{
int Turns = Convert.ToInt32(e.Outputs["Turns"]);
Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns);
syncEvent.Set();
},
Aborted = delegate (WorkflowApplicationAbortedEventArgs e)
{
Console.WriteLine(e.Reason);
syncEvent.Set();
},
OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e)
{
Console.WriteLine(e.UnhandledException.ToString());
return UnhandledExceptionAction.Terminate;
},
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)
{
if (!Int32.TryParse(Console.ReadLine(), out int Guess))
{
Console.WriteLine("Please enter an integer.");
}
else
{
validEntry = true;
wfApp.ResumeBookmark("EnterGuess", Guess);
}
}
}
}
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