Udostępnij za pośrednictwem


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

  1. Otwórz rozwiązanie z poprzedniego tematu Porady: tworzenie tematu działania przy użyciu programu Visual Studio 2012.

  2. 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.

  3. 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.

  4. 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.

  5. 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

  1. 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 zastąp ciąg Workflow1 , SequentialNumberGuessWorkflowlub 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.

    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();
    
    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

  1. Dodaj następującą instrukcję w górnej części Program.cs lub Module1.vb poniżej istniejących using instrukcji lub Imports .

    using System.Collections.Generic;
    using System.Threading;
    
    Imports System.Collections.Generic
    
  2. 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 , SequentialNumberGuessWorkflowlub 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.

    var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } };
    
    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1(), 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

  1. Zmodyfikuj procedurę obsługi, Completed aby pobrać i wyświetlić liczbę zmian używanych przez przepływ pracy.

    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.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ę

  1. 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)
    
  2. 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.

    wfApp.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żywa idleEvent instrukcji i syncEvent 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.

  3. Usuń wywołanie metody WaitOnei 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)
        {
            int Guess;
            if (!Int32.TryParse(Console.ReadLine(), out 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ę

  1. Kliknij prawym przyciskiem myszy pozycję NumberGuessWorkflowHost w Eksplorator rozwiązań i wybierz pozycję Ustaw jako projekt startowy.

  2. 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 , FlowchartNumberGuessWorkflowSequentialNumberGuessWorkflowlub StateMachineNumberGuessWorkflow, 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 WorkflowApplication(new Workflow1(), 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 , SequentialNumberGuessWorkflowlub 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 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);
            }
        }
    }
}
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

Zobacz też