Übersetzung vorschlagen
 
Andere Vorschläge:

progress indicator
Keine anderen Vorschläge
MSDN Magazin > Home > Ausgaben > 2009 > MSDN Magazin August 2009 >  Grundlagen: Windows Workflow-Entwurfsmuster
Inhalt anzeigen:  Englisch mit deutscher ÜbersetzungInhalt anzeigen: Englisch mit deutscher Übersetzung
Dies sind maschinell übersetzte Inhalte, die von den Mitgliedern der Community bearbeitet werden können. Sie können die Übersetzung verbessern, indem Sie auf den jeweils zum Satz gehörenden Link "Bearbeiten" klicken.Mithilfe des Dropdown-Steuerelements "Inhalt anzeigen" links oben auf der Seite können Sie zudem bestimmen, ob nur der englische Originaltext, nur die deutsche Übersetzung oder beides nebeneinander angezeigt werden.
Foundations
Windows Workflow Design Patterns
Matthew Milner
Code download available from the MSDN Code Gallery
Browse the Code Online
Design patterns provide a common, repeatable approach to solving software development tasks, and many different patterns can describe how to accomplish a certain goal in code. When developers begin working with Windows Workflow Foundation (WF), they often ask about how to accomplish common tasks with the technology. This month I discuss several design patterns used in WF.

Doing Work for N Items of Data
Often, workflows are not driven purely by logic but also by data, such as a list of people in an organization or a list of orders, where a set of steps in the workflow needs to execute once for each item. Although perhaps not a pattern in itself, this simple, reusable bit of logic is an important component of the other patterns I discuss in this article. The key to this scenario is using the Replicator activity to iterate over a collection of data and execute the same activities for each item in the collection.
The Replicator activity provides a property for the collection of data items that drives the iterations, events for initializing the child activities for each data item, and conditions to enable you to break out of the execution. Essentially, the Replicator activity provides you with ForEach semantics coupled with DoWhile-style conditional execution.
For example, given a workflow with a property of type List<string> containing employee e-mail addresses, you can iterate over the list and send a message to each employee, as shown in Figure 1.
Figure 1 Replicator with SendMail Activity
In this scenario, the Replicator activity must have the InitialChildData property bound to a collection implementing the IEnumerable interface that contains the e-mail addresses to be used. These addresses are used to set the recipient's address for each iteration. By handling the ChildInitialized event, you gain access to the data item and the dynamic activity instance that is executed. Figure 2 shows how the e-mail address from the collection is passed to the event and can be used to set the RecipientAddress property on the related e-mail activity instance.
public List<string> emails = new List<string>
  {"matt@contoso.com","msdnmag@example.com"};

private void InitChildSendMail(object sender, ReplicatorChildEventArgs e)
{
    SendMailActivity sendMail = e.Activity as SendMailActivity;
    sendMail.RecipientAddress = e.InstanceData.ToString();
}
The Replicator activity can execute either sequentially or in parallel. In sequential mode, Replicator waits for each iteration to complete before beginning a new iteration. In parallel mode, all activities are initialized and scheduled at the same time, and the execution is much like the Parallel activity, except with the same definition in each branch. Being able to iterate over data items, invoke some actions in parallel, and wait for responses for each item is critical in many design patterns, including several discussed in this article.

Listen with Timeout
In the Listen with Timeout scenario, you have a requirement to wait for some input, but only for a certain amount of time. For example, you might have notified a manager with an e-mail message and need to wait for a reply, but if the manager does not respond within a certain period of time, your workflow should take further action, such as sending a reminder.
The heart of any implementation of this pattern is the Listen activity. The Listen activity allows a workflow to pause and wait for many different events or inputs at the same time. This capability can also be accomplished with the Parallel activity, but the difference is that the Listen activity reacts when the first event occurs and stops listening for all other events, whereas the Parallel activity waits for all events. Combining this functionality with the ability to wait for a designated amount of time, provided by the Delay activity, lets a workflow wait for an event but timeout if the event does not occur. Figure 3 shows a Listen activity waiting for messages to arrive via Windows Communication Foundation (WCF) or for the timeout to expire. Notice that the Listen activity can have multiple branches and can therefore be listening for many different events at the same time.
Figure 3 Listen Activity with Multiple Branches
An implementation like this enables a workflow to wait for a certain amount of time for a response. Typically, if the timeout occurs, the workflow is designed to take appropriate actions. To expand on the manager approval example, once the timeout occurs, the manager should be reminded that she has an outstanding request she needs to approve. After the manager is reminded, the workflow needs to be restored to a state of waiting for the response and the timeout. Surrounding a Listen with a While activity enables the workflow to continue waiting until a certain condition is met. Inside the branches of the Listen activity, the condition is manipulated appropriately to continue waiting or to move on after the response that is wanted is received. In a simple case, a flag can be used to manage the condition, causing the While activity to loop until the flag is set. Thus, when the manager sends a response, the flag can be set and the While activity closes, allowing the workflow to move on to the next activity. In the branch with the Delay activity, after the delay occurs, activities are used to send a reminder to the manager and to ensure that the condition is still set to force the While activity to schedule the child activities again, as shown in Figure 4.
Figure 4 Listen with While to Send Reminders
In this example, the trigger condition to stop waiting is simply a response from the manager, but, of course, any level of complex evaluation can be done on the input data received. One option is to use a rule set and the Policy activity to determine whether all conditions have been met to move to the next step in the workflow.

Variation: State Machine
One variation on the Listen with Timeout pattern occurs when you develop a State Machine workflow instead of a Sequential workflow. In this case, the State activity takes the place of the Listen activity and provides the ability to listen for multiple events at the same time, including using the Delay activity. In a given state, say, Waiting For Approval, you can model the same scenario as before, where you wait for a response or the timeout. Figure 5 shows a sample workflow implementing the same logic as before but using a State Machine workflow.
Figure 5 State Machine Listening
It is actually simpler to manage the conditions here because there is no need for a While activity. Instead, when the delay occurs, you can send the reminder or take other actions and then transition back to the current state by using the SetState activity, which causes the Delay activity to execute again, resetting the timeout. If the response is received and meets the conditions for continuing, you use the SetState activity to move to the next state. Both branches are shown in Figure 6.
Figure 6 Listening in a State Activity

Scatter Gather
When you have the need to start many child workflows to do some work, use the Scatter Gather pattern. These workflows might all be doing the same work over different data, or each might be doing different work. The goal is to start all the work, optimize the use of multiple threads to accomplish the tasks faster if possible, and then notify the parent workflow when each task is complete to collect the results.
You can start multiple workflows simply by using the Replicator activity and the InvokeWorkflow activity. The workflows are started asynchronously, which is what you want, but it makes waiting in the parent workflow more challenging because you need a blocking activity that can receive the data back from the child workflows. Using the Receive activity, the parent workflow can wait for each child activity to finish and receive any results back from each workflow that was started. The high-level view of this pattern in the parent workflow is shown in Figure 7.
Figure 7 Replicator with InvokeWorkfl ow and Receive Activities
The figure makes this pattern look simple to implement, but several key steps are needed to ensure that the child workflows can correctly call back to the parent workflow using WCF. Context information needs to be passed from the parent workflow to each child to enable the child to send data back to the parent workflow, including the workflow instance identifier and the conversation identifier to select the correct Receive activity. Additionally, the parent workflow must be hosted as a WCF service to enable the communication, but it needs to be started using WorkflowRuntime, as shown in Figure 8.
WorkflowServiceHost host = new WorkflowServiceHost(typeof(MSDN.Workflows.
  ParentWorkflow));

try
{
    host.Open();
    WorkflowRuntime runtime = host.Description.Behaviors.
      Find<WorkflowRuntimeBehavior>().WorkflowRuntime;
    WorkflowInstance instance = runtime.CreateWorkflow(
      typeof(MSDN.Workflows.ParentWorkflow));
    instance.Start();
    Console.ReadLine();
}
catch (Exception ex)
{
    Console.WriteLine(ex);
    Console.ReadLine();
}
finally
{
    if (host != null && host.State == CommunicationState.Opened)
        host.Close();
    else
        host.Abort();
}
Each child workflow needs to have input parameters for at least the parent workflow ID and the receive activity ID, in addition to any business data that needs to be processed in the child workflow. Parameters to the workflow are defined as public properties on the workflow definition.
The InvokeWorkflow activity allows you to pass parameters to the child workflow and surfaces those properties in the property dialog box. The parameters on the InvokeWorkflow activity can be bound to a property or to a field in the workflow. However, when using the Replicator activity to invoke many workflows, the parameters need to be set in code because each invocation requires unique values; for each iteration, the property or field can be set with the current inputs. Therefore, the parameters on the InvokeWorkflow activity should be bound to fields in the workflow, and those fields will be updated in your code before the child workflow is created.
Your initial inclination might be to set the property during the ChildInitialized event for the Replicator, as I showed with the SendMail example earlier, and this is a good place to start. However, when executing the Replicator activity in parallel mode, all the children are initialized before any instances begin to execute. Therefore, if you set the property in the ChildInitialized event, by the time the InvokeWorkflow activity executes, all instances of the activity would use a single set of data. However, the ChildInitialized event does provide access to the activity instance and the data item driving the iteration. One approach is to collect the data item and store it with a unique identifier so that it can be related to the correct activity instance during execution. Figure 9 shows the ChildInitialized event handler for the Replicator activity where the instance data is stored in a dictionary keyed on the unique identifier for the ActivityExecutionContext.
private void InitChild(object sender, ReplicatorChildEventArgs e)
{
    InvokeWorkflowActivity startWF =
      (InvokeWorkflowActivity)e.Activity.GetActivityByName("StartChild
        Workflow");
    InputValueCollection[(Guid)e.Activity.GetValue(
    Activity.ActivityContextGuidProperty)] = e.InstanceData.ToString();
}
Next, to initialize the InvokeWorkflow activity, you use the Invoking event to set up the parameters. At this point in the execution, all the values needed for input to the child workflow are available. The workflow identifier can be retrieved from the WorkflowEnvironment, and the conversation identifier can be retrieved from the context property on the Receive activity instance. Finally, the business data can be retrieved using the identifier for the current execution context. Figure 10 shows the code to initialize the parameter to be passed to the workflow.
private void PrepChildParams(object sender, EventArgs e)
{
    InvokeWorkflowActivity startWf = sender as InvokeWorkflowActivity;
    ReceiveActivity receive =
      (ReceiveActivity)startWf.Parent.GetActivityByName(
        "ReceiveChildCompletion");
    Contracts.ChildWFRequest request = new Contracts.ChildWFRequest();
    request.WFInstanceID = WorkflowEnvironment.WorkflowInstanceId.ToString();
    request.ConversationID = receive.Context["conversationId"];
    request.RequestValue =
      InputValueCollection[(Guid)startWf.Parent.GetValue(
    Activity.ActivityContextGuidProperty)];
    StartWF_Input = request;
}
After the child workflow is started, it can begin to execute the work to be done and, on completion, use the Send activity to notify the parent workflow. Before sending the message, the context must be set on the Send activity to ensure that the message gets sent to the correct Receive activity in the parent workflow. Using the values passed from the parent, the context can be correctly set using the BeforeSend event, as shown here.
e.SendActivity.Context = new Dictionary<string, string>{
                {"instanceId", InputValues.WFInstanceID},
                {"conversationId", InputValues.ConversationID}};
With all these parts in place, the parent workflow starts, and the Replicator activity iterates over the collection of data, starting one child workflow for each item and waiting for a message back from each in parallel. Then, as the child workflows finish, they send a message back to the parent, which can continue processing after all the child workflows have reported back their results. Using this approach, the child workflows can be running at the same time, each with its own thread, providing truly asynchronous processing.

Starting Workflow Services with Multiple Operations
In many samples, workflow services start with a single Receive activity modeling a single operation. In the scenario I've discussed here, you have a need to start the workflow service with more than one method call. That is, the client application might not always invoke the same operation to begin interacting with your workflow, and you need to be able to design the workflow so that it can be started on the basis of multiple operations.
There are actually two different varieties of this pattern, depending on how you want to handle requests after the first request. The first option is to enable the workflow to start with one of several operations and, after that operation is complete, move on with the workflow processing until you define another point where operations can be called. To accomplish this goal, you need to return to the Listen activity and use it as the first activity in your workflow definition. Then, in each branch of the activity, add a Receive activity, configure it with the appropriate service operation information, and bind any necessary parameters for processing, as shown in Figure 11.
Figure 11 Multiple Receive Activities in a Listen Activity
The crucial step is to ensure that all the Receive activities in the Listen activity have the CanCreateInstance property set to True. This instructs the WCF runtime that if no context information is available on the request indicating an existing workflow instance, it is okay to start a new instance based on the configured operation. Although it might seem slightly odd to create the workflow with an activity other than Receive, the runtime creates the instance, then starts, and only then attempts to send the contents of the WCF message to the Receive activity. In this case, once the workflow starts, both Receive activities are executing and waiting for input.
I mentioned that there are two variations of this pattern. When you use the Listen activity as I did in the previous example, one of the operations starts the workflow, but then the Listen activity completes after that single branch is done and the service is no longer able to receive requests for the other operations modeled in the Listen. This might be exactly what you want in some scenarios, but in others you want the workflow to handle an entire set of operations before it moves on. That is, you know the workflow will receive several requests on different operations in the service contract, but you are not sure which request will be first. In this case, instead of the Listen activity, you can use the Parallel activity with each branch containing a Receive activity with its CanCreateInstance property set to True. This still allows the workflow to start with any operation, but it also keeps the workflow in a state to receive all the other operation calls modeled in the various branches.
Finally, when using a State Machine workflow, you have more flexibility in how the workflow behaves when a particular message is received. Consider a state machine in which the initial state contains several event-driven activities, each with a Receive activity as the starting activity, and each Receive marked to enable creation. Normally, the State activity acts much like the Listen activity, but as the developer, you decide when control moves from the current state to another state. When the Listen activity completes, it closes, and control moves to the next activity in the sequence. With a State activity, after a branch executes, if the workflow does not move to a new state, the workflow remains in the current state and continues to wait for the defined inputs.
To use semantics such as the Listen activity, you must use the SetState activity to move the workflow to the next state when one of the operations is invoked. This usually puts the workflow into a state in which it is waiting for different WCF operations to be invoked. If, on the other hand, you want semantics closer to the Parallel model, where all the operations must be invoked but not in a particular order, then after each Receive activity you have the choice of not changing state or of using the SetState activity to transition back to the same state, a self-transition.
This last option is not entirely like the Parallel activity model in one potentially significant manner. With the Parallel activity, after an operation has been called, it cannot be called again unless modeled somewhere after the Parallel activity. In the state machine model, after the operation is invoked, if the workflow remains in the same state, it can receive messages for the other operations or the original operation. In effect, the state can provide you with semantics similar to a Listen activity in a While activity, waiting for all events, reacting to a single event, and then looping back and waiting for all those same events again.

Send your questions and comments to mmnet30@microsoft.com.

Matt Milner is a member of the technical staff at Pluralsight, where he focuses on connected systems technologies (WCF, Windows Workflow, BizTalk, "Dublin," and the Azure Services Platform). Matt is also an independent consultant specializing in Microsoft .NET application design and development. Matt regularly shares his love of technology by speaking at local, regional, and international conferences such as Tech. Ed. Microsoft has recognized Matt as an MVP for his community contributions around connected systems technology. Contact Matt via his blog: pluralsight.com/community/blogs/matt/.

Grundlagen
Windows Workflow-Entwurfsmuster
Matthew Milner
Herunterladen von Code von der MSDN Code Gallery verfügbar
Code online durchsuchen
Entwurfsmuster bieten einen allgemeinen, wiederholbaren Ansatz für die Lösung von Softwareentwicklungsaufgaben, und viele verschiedene Muster können beschreiben, wie ein bestimmtes Ziel im Code erreicht wird. Wenn Entwickler mit Windows Workflow Foundation (WF) zu arbeiten beginnen, fragen Sie oft, wie häufig ausgeführte Aufgaben mit der Technologie bewerkstelligt werden. Diesen Monat diskutieren ich mehrere Entwurfsmuster in WF verwendet.

Ausführen von Aufgaben für N Elemente von Daten
Häufig werden Workflows nicht gesteuert ausschließlich durch Logik, sondern auch durch Daten, z. B. eine Liste von Personen in einer Organisation oder eine Liste der Bestellungen, einmal für jedes Element ausführen, muss eine Reihe von Schritten im Workflow. Zwar vielleicht keinem Muster in sich selbst, ist dieses einfache, wiederverwendbare Bit der Logik eine wichtige Komponente der Muster, die in diesem Artikel besprochen. Der Schlüssel für dieses Szenario wird mithilfe der Replicator-Aktivität Durchlaufen einer Auflistung von Daten und führen die gleichen Aktionen für jedes Element in der Auflistung.
Die Replicator-Aktivität stellt eine Eigenschaft für die Auflistung der Datenelemente, die die Iterationen Ereignisse zum Initialisieren der untergeordneten Aktivitäten für jedes Datenelement und Bedingungen, um Sie aus der Ausführung unterbrechen können Laufwerke bereit. Im Wesentlichen bietet die Replicator-Aktivität ForEach-Semantik gekoppelt mit bedingte Ausführung DoWhile-Stil.
Betrachten Sie beispielsweise einen Workflow mit einer Eigenschaft vom Typ List < String >Mitarbeiter e-Mail-Adressen enthält, können Sie die Liste durchlaufen und eine Nachricht an jeden Mitarbeiter senden, wie in Abbildung 1 dargestellt.
Abbildung 1 Replicator mit SendMail Aktivität
In diesem Szenario benötigen die Replicator-Aktivität, die InitialChildData-Eigenschaft auf eine Implementierung der IEnumerable-Schnittstelle, die mit den e-Mail-Adressen verwendet werden, die Auflistung gebunden werden. Diese Adressen werden verwendet, um die Empfängeradresse für jede Iteration festzulegen. Durch ChildInitialized-Ereignis behandelt, erhalten Sie Zugriff auf das Datenelement und die dynamische Aktivitätsinstanz, die ausgeführt wird. Abbildung 2 zeigt, wie die e-Mail-Adresse aus der Auflistung an das Ereignis übergeben, und kann zum Festlegen der RecipientAddress-Eigenschaft für die zugehörige e-Mail-Aktivitätsinstanz verwendet werden.
public List<string> emails = new List<string>
  {"matt@contoso.com","msdnmag@example.com"};

private void InitChildSendMail(object sender, ReplicatorChildEventArgs e)
{
    SendMailActivity sendMail = e.Activity as SendMailActivity;
    sendMail.RecipientAddress = e.InstanceData.ToString();
}
Die Replicator-Aktivität kann sequenziell oder parallel ausgeführt. In sequenziellen Modus wartet Replicator für jede Iteration um vor Beginn einer neuen Iteration abzuschließen. Im parallelen Modus alle Aktivitäten initialisiert und zur gleichen Zeit geplant sind, und die Ausführung ist ähnlich wie die Parallel-Aktivität, außer mit der gleichen Definition in jeder Verzweigung. Können Datenelemente durchlaufen, einige Aktionen parallel aufgerufen und Warten auf Antworten für jedes Element ist in vielen Entwurfsmuster, einschließlich mehrerer in diesem Artikel beschriebenen entscheidender Bedeutung.

Überwachen mit Timeout
In den Listen mit Timeout Szenario haben Sie eine Anforderung für Eingaben, jedoch nur für eine bestimmte Zeitspanne warten. Beispielsweise Sie möglicherweise benachrichtigt haben ein Manager mit einer e-Mail-Nachricht und müssen warten, eine Antwort, aber wenn den Manager nicht innerhalb von eine gewisse Zeit, reagiert Ihren Workflow weitere Aktion such as eine Mahnung senden ergreifen sollten.
Das Kernstück jeder Implementierung der dieses Muster ist die Aktivität überwachen. Die Listen-Aktivität ermöglicht einen Workflow anhalten und für viele verschiedene Ereignisse oder Eingaben zur gleichen Zeit warten. Diese Funktion kann auch mit der Aktivität parallel durchgeführt, aber der Unterschied besteht darin, dass die Listen-Aktivität Wenn das erste Ereignis tritt ein, und ist nicht empfangsbereit für alle anderen Ereignisse, reagiert während alle Ereignisse, die parallele-Aktivität wartet. Kombinieren diese Funktionalität die Möglichkeit, eine festgelegte Zeitspanne von der Aktivität Verzögerung bereitgestellten warten kann einen Workflow auf ein Ereignis aber Timeout zu warten, tritt das Ereignis nicht auf. Abbildung 3 zeigt eine Listen-Aktivität wartet für Nachrichten, die über Windows Communication Foundation (WCF) eintreffen oder der Timeout abläuft. Beachten Sie, dass die Listen-Aktivität mehrere Zweige kann und daher für viele verschiedene Ereignisse gleichzeitig Abfragen werden kann.
Abbildung 3 Listen Aktivität mit mehreren Verzweigungen
Eine Implementierung sieht ermöglicht einem Workflow zu einer bestimmten Zeitspanne für eine Antwort warten. In der Regel erfolgt das Timeout auf, der Workflow dient zum entsprechenden Aktionen. Zum Beispiel Genehmigung-Manager zu erweitern, sobald das Timeout auftritt sollte der Manager erinnert werden, dass Sie eine ausstehende Anforderung hat, die Sie genehmigen muss. Nach der Manager Erinnerung ist, muss der Workflow in einen Zustand wartet die Antwort und das Timeout wiederhergestellt werden. Umgibt einen Listen mit einer While ermöglicht Aktivität im Workflow weiterhin warten, bis eine bestimmte Bedingung erfüllt ist. In den Verzweigungen der Listen-Aktivität wird die Bedingung entsprechend bearbeitet, weiterhin warten, oder verschieben auf nach Empfang der Antwort, die gewünscht wird. In einem einfachen Fall kann ein Flag zum Verwalten der Bedingung, verursacht die While verwendet werden Aktivität, bis das Flag festgelegt ist. Also wenn der Manager eine Antwort sendet, das Flag kann festgelegt werden und die While Aktivität schließt, ermöglichen den Workflow, um nach der nächsten Aktivität auf. In der Verzweigung mit der Aktivität Verzögerung, nachdem die Verzögerung auftritt, Aktivitäten werden verwendet, um eine Erinnerung an den Manager senden und sicherstellen, dass die Bedingung immer noch festgelegt wird, erzwingen Sie die While Aktivität, die untergeordneten Aktivitäten erneut planen, wie in Abbildung 4 dargestellt.
Abbildung 4 hören mit beim Senden von Erinnerungen
In diesem Beispiel die Auslöserbedingung beenden warten ist einfach eine Antwort vom Manager aber selbstverständlich kann jeder Ebene der komplexen Auswertung der empfangenen Eingabedaten durchgeführt werden. Eine Option ist die Verwendung eines Regelsatzes und die Policy-Aktivität um zu bestimmen, ob alle Bedingungen erfüllt wurden, um auf die nächste Schritt in den Workflow zu verschieben.

Variante: Statuscomputer
Eine Variation auf der Listen mit Timeout Muster tritt auf, wenn Sie einen Workflow Statuscomputer anstatt eines sequenziellen Workflows entwickeln. In diesem Fall die State-Aktivität erfolgt der Listen-Aktivität und ermöglicht das mehrere Ereignisse zur gleichen Zeit, einschließlich der Verwendung der Delay-Aktivität überwachen. In einem bestimmten Zustand können sagen, ausstehende zur Genehmigung Sie modellieren dasselbe Szenario vor, in dem Sie eine Antwort oder das Timeout warten. Abbildung 5 zeigt einen Beispielworkflow Implementierung derselben Logik wie vor aber einen Statuscomputer Workflow verwenden.
Abbildung 5 Statuscomputer Abhören
Ist es tatsächlich einfacher, die Bedingungen hier verwalten, da keine Notwendigkeit für eine While besteht-Aktivität. Stattdessen tritt die Verzögerung können die Erinnerung zu senden oder andere Aktionen und dann Übergang in den aktuellen Zustand mithilfe der SetState-Aktivität, wodurch die Verzögerung Aktivität wieder ausführen Zurücksetzen des Zeitlimits. Wenn die Antwort empfangen wird und die Bedingungen erfüllt für die Fortsetzung, verwenden Sie SetState-Aktivität, um zum nächsten Status zu verschieben. Beiden Verzweigungen sind in Abbildung 6 dargestellt.
Abbildung 6 In eine State-Aktivität Überwachung

Punkte sammeln
Wenn Sie die Notwendigkeit, starten Sie viele untergeordnete Workflows dazu einige arbeiten, verwenden Sie das Sammeln von Punkt-Muster. Diese Workflows möglicherweise alle werden dadurch die gleiche Arbeit über unterschiedliche Daten oder jeder werden unterschiedliche arbeiten ausführen. Das Ziel ist die Arbeit beginnen, Optimieren der Verwendung mehrerer Threads die schnellere möglichst Aufgaben und dann den übergeordneten Workflow benachrichtigen, wenn jede Aufgabe zum Sammeln der Ergebnisse abgeschlossen ist.
Sie können mehrere Workflows einfach mithilfe der Replicator-Aktivität und die InvokeWorkflow-Aktivität starten. Die Workflows werden gestartet asynchron, die Ihren Wünschen entspricht, macht jedoch warten in der übergeordneten Workflow schwieriger weil Sie eine Blockierung Aktivität, die die Daten wieder vom untergeordneten Workflows empfangen können. Verwenden die Aktivität empfangen, kann der übergeordneten Workflow warten jedes untergeordneten Aktivitäten abgeschlossen und keine Ergebnisse von jeder Workflow, der gestartet wurde empfangen. Die allgemeinen dieses Muster im übergeordneten Workflow ist im Abbildung 7 zeigt.
Abbildung 7 Replicator mit InvokeWorkfl ow und Aktivitäten erhalten
In der Abbildung macht dieses Muster aussehen, einfach zu implementieren, aber mehrere Schlüssel Schritte notwendig sind, um sicherzustellen, dass die untergeordneten Workflows korrekt zurück an den übergeordneten Workflow mithilfe von WCF aufrufen können. Kontextinformationen muss von der übergeordneten Workflow an jedes untergeordnete Element So aktivieren Sie die untergeordneten Daten zurück an den übergeordneten Workflow, einschließlich des Instanzbezeichners Workflow und der Unterhaltung Bezeichner, wählen Sie die richtige empfangen Aktivität Senden übergeben werden. Darüber hinaus der übergeordneten Workflow muss als WCF-Dienst so aktivieren Sie die Kommunikation gehostet werden, aber es muss mit WorkflowRuntime-, gestartet werden, wie in Abbildung 8 dargestellt.
WorkflowServiceHost host = new WorkflowServiceHost(typeof(MSDN.Workflows.
  ParentWorkflow));

try
{
    host.Open();
    WorkflowRuntime runtime = host.Description.Behaviors.
      Find<WorkflowRuntimeBehavior>().WorkflowRuntime;
    WorkflowInstance instance = runtime.CreateWorkflow(
      typeof(MSDN.Workflows.ParentWorkflow));
    instance.Start();
    Console.ReadLine();
}
catch (Exception ex)
{
    Console.WriteLine(ex);
    Console.ReadLine();
}
finally
{
    if (host != null && host.State == CommunicationState.Opened)
        host.Close();
    else
        host.Abort();
}
Jeder untergeordnete Workflow muss für mindestens Eingabeparameter haben die übergeordneten Workflow-ID und das Empfangen Aktivität-ID, zusätzlich zu den geschäftlichen Daten, die im Workflow untergeordneten verarbeitet werden müssen. Parameter für den Workflow werden als öffentliche Eigenschaften in der Workflowdefinition definiert.
Die InvokeWorkflow-Aktivität können Sie Parameter an den untergeordneten Workflow übergeben und diese Eigenschaften im Dialogfeld Eigenschaft bereitstellt. Die Parameter für die InvokeWorkflow-Aktivität können an eine Eigenschaft oder an ein Feld in den Workflow gebunden werden. Allerdings müssen Wenn Replicator-Aktivität verwenden, um viele Workflows aufrufen, die Parameter im Code festgelegt werden, da jeder Aufruf eindeutige Werte; erfordertfür jede Iteration kann die Eigenschaft oder Feld mit den aktuellen Eingaben festgelegt werden. Daher die Parameter für die Aktivität InvokeWorkflow sollte auf Felder in den Workflow gebunden werden, und diese Felder werden in Ihrem Code aktualisiert, bevor der untergeordneten Workflow erstellt wird.
Die anfängliche Ansichtsneigung bestimmt möglicherweise für die Eigenschaft während der ChildInitialized-Ereignisses der Benutzerreplikationsdienst eingestellt wurde mit dem SendMail-Beispiel weiter oben, und dies ist ein guter starten. Jedoch werden beim Ausführen der Replicator-Aktivität im parallelen Modus alle untergeordneten Elemente initialisiert vor alle Instanzen ausgeführt werden. Daher würden Festlegen der Eigenschaft im ChildInitialized-Ereignis, durch die Zeit der InvokeWorkflow Aktivität ausgeführt wird, alle Instanzen der Aktivität einen einzelnen Satz von Daten verwenden. Das ChildInitialized-Ereignis stellt jedoch Zugriff auf die Aktivitätsinstanz und das Steuern der Iteration Datenelement zur Verfügung. Ein Ansatz besteht darin, das Datenelement sammeln und mit einem eindeutigen Bezeichner speichern, sodass es während der Ausführung an die richtige Aktivitätsinstanz verknüpft werden kann. Abbildung 9 zeigt den ChildInitialized-Ereignishandler für die Replicator-Aktivität, in dem die Instanzdaten in ein Wörterbuch mit Schlüsseln auf den eindeutigen Bezeichner für die ActivityExecutionContext gespeichert.
private void InitChild(object sender, ReplicatorChildEventArgs e)
{
    InvokeWorkflowActivity startWF =
      (InvokeWorkflowActivity)e.Activity.GetActivityByName("StartChild
        Workflow");
    InputValueCollection[(Guid)e.Activity.GetValue(
    Activity.ActivityContextGuidProperty)] = e.InstanceData.ToString();
}
Anschließend verwenden um die InvokeWorkflow-Aktivität zu initialisieren, Sie das Ereignis aufrufen können Sie die Parameter einrichten. Zu diesem Zeitpunkt sind bei der Ausführung alle Werte, die für die Eingabe für den untergeordneten Workflow benötigt verfügbar. Die Workflow-ID aus der WorkflowEnvironment abgerufen werden kann, und der Unterhaltung Bezeichner kann aus der Kontexteigenschaft auf der Instanz empfangen Aktivität abgerufen werden. Schließlich können die Geschäftsdaten mithilfe des Bezeichners für den aktuellen Ausführungskontext abgerufen werden. Abbildung 10 zeigt den Code zum Initialisieren des Parameter an den Workflow übergeben werden.
private void PrepChildParams(object sender, EventArgs e)
{
    InvokeWorkflowActivity startWf = sender as InvokeWorkflowActivity;
    ReceiveActivity receive =
      (ReceiveActivity)startWf.Parent.GetActivityByName(
        "ReceiveChildCompletion");
    Contracts.ChildWFRequest request = new Contracts.ChildWFRequest();
    request.WFInstanceID = WorkflowEnvironment.WorkflowInstanceId.ToString();
    request.ConversationID = receive.Context["conversationId"];
    request.RequestValue =
      InputValueCollection[(Guid)startWf.Parent.GetValue(
    Activity.ActivityContextGuidProperty)];
    StartWF_Input = request;
}
Nach der untergeordneten Workflow gestartet wird, können Sie beginnen, Ausführen die Arbeit durchgeführt werden, und verwenden Sie bei Fertigstellung der Send-Aktivität, damit den übergeordneten Workflow benachrichtigt. Um sicherzustellen, dass die Nachricht an die richtige empfangen Aktivität im Workflow übergeordneten gesendet ruft muss vor dem Senden der Nachricht, der Kontext für die Aktivität senden festgelegt werden. Verwenden die Werte vom übergeordneten Objekt übergeben, kann der Kontext korrekt mit festgelegt werden das BeforeSend-Ereignis, wie hier gezeigt.
e.SendActivity.Context = new Dictionary<string, string>{
                {"instanceId", InputValues.WFInstanceID},
                {"conversationId", InputValues.ConversationID}};
Alle diese Teile in Ort, der übergeordneten Workflow gestartet wird und der Replikator Aktivität die Sammlung der Daten durchläuft starten einen untergeordneten Workflows für jedes Element, und Warten auf eine Nachricht von einzelnen parallel. Dann wie die untergeordneten Workflows abgeschlossen haben, senden Sie eine Nachricht zurück an den übergeordneten fortfahren kann verarbeitet werden, nachdem alle untergeordneten Workflows wieder Ihre Ergebnisse gemeldet haben. Bei diesem Ansatz können zur gleichen Zeit, jedes mit seinem eigenen Thread, wirklich asynchronen Verarbeitung bereitstellen untergeordneten Workflows ausgeführt werden.

Workflowdienste mit mehreren Operationen beginnen
Starten in vielen Beispielen Workflowdienste mit einer einzelnen empfangen Aktivität Modellieren einer einzigen Operation. In dem Szenario hier erläuterten haben, haben Sie müssen den Workflowdienst mit mehr als einen Methodenaufruf zu starten. Die Client-Anwendung könnte nicht immer die gleiche Operation beginnen mit dem Workflow interagieren aufrufen, und Sie müssen in der Lage den Workflow entwerfen, damit er auf Grundlage der mehrere Vorgänge gestartet werden kann.
Es gibt eigentlich zwei unterschiedliche Arten von dieses Muster, abhängig davon, wie Anforderungen nach der ersten Anforderung verarbeitet werden sollen. Die erste Option ist zum Aktivieren des Workflows mit eines mehrere Vorgänge beginnen und, nachdem der Vorgang abgeschlossen ist, verschieben Sie auf mit der Workflow-Verarbeitung, bis Sie einen anderen Punkt definieren, in denen Operationen aufgerufen werden kann. Zu diesem Zweck müssen Sie zurück zum Listen-Aktivität und als erste Aktivität in Ihre Workflowdefinition verwenden. Fügen Sie dann in jeder Verzweigung der Aktivität eine Aktivität empfangen, mit den entsprechenden Vorgang Dienstinformationen konfigurieren Sie und binden Sie alle erforderlichen Parameter für die Verarbeitung wie dargestellt in Abbildung 11.
Abbildung 11 Mehrere Aktivitäten in einem Listen Aktivität empfangen
Wichtige Schritt wird sichergestellt, dass alle Receive-Aktivitäten in der Listen-Aktivität die CanCreateInstance-Eigenschaft auf True festgelegt. Dies weist der WCF-Laufzeit werden, ist keine Kontextinformationen verfügbar bei der Anforderung, die eine vorhandenen Workflowinstanz angibt, eine neue Instanz aufgrund der konfigurierten Operation starten kann. Obwohl es etwas ungerade zum Erstellen des Workflows mit einer Aktivität außer empfangen mag, erstellt die Laufzeit der Instanz, dann wird gestartet und nur dann versucht, den Inhalt der WCF-Nachricht an die Aktivität empfangen senden. Nachdem der Workflow startet, werden beide Receive-Aktivitäten in diesem Fall ausführen und Warten auf Eingabe.
Es gibt zwei Varianten dieses Muster erwähnt. Wenn Sie der Listen-Aktivität verwenden wie ich im vorherigen Beispiel wurde, eine der Operationen den Workflow startet, aber die Listen-Aktivität führt anschließend nach, dass einzelne Verzweigung erfolgt und der Dienst ist nicht mehr empfangen, Anforderungen für die anderen Vorgänge in den Listen modelliert. Dies möglicherweise genau gewünschten in einigen Szenarios, aber in anderen Workflow einen ganzen Satz von Operationen behandeln, bevor er verschiebt auf soll. Wissen, dass Sie der Workflow erhalten mehrere Anforderungen für unterschiedliche Vorgänge im Servicevertrag, aber Sie sind nicht sicher, dass die Anforderung erste wird. In diesem Fall können Sie die parallele-Aktivität anstelle der Aktivität Listen mit jeder Verzweigung enthält eine Aktivität empfangen, deren CanCreateInstance-Eigenschaft auf True festgelegt. Dadurch wird des Workflows mit jeder Vorgang starten noch, auch den Workflow in einem Zustand, die alle der andere Vorgang Aufrufe in unterschiedlichen Verzweigungen modelliert empfangen behält jedoch.
Schließlich verfügen durch die einen Statuscomputer Workflow verwenden, mehr Flexibilität wie der Workflow verhält, wenn eine bestimmte Nachricht empfangen wird. Berücksichtigen Sie einen Statuscomputer in dem der anfängliche Zustand enthält mehrere ereignisgesteuerte Aktivitäten mit einer Aktivität empfangen als erste Aktivität, und jede empfangen gekennzeichnet, damit erstellen. In der Regel entscheiden die Statusaktivität ähnlich wie die Aktivität überwachen, jedoch als Entwickler fungiert, Sie wenn Steuerelement von den aktuellen Zustand in einen anderen Status wechselt. Nach Abschluss die Listen-Aktivität geschlossen und Steuerelement verschiebt zur nächsten Aktivität in der Reihenfolge. Mit einer Statusaktivität nach eine Verzweigung, führt Wenn der Workflow nicht auf einen neuen Status, verschiebt der Workflow verbleibt im aktuellen Zustand und weiterhin warten, bis die definierten Eingaben.
Semantik wie die Listen-Aktivität verwenden möchten, müssen Sie die SetState-Aktivität verwenden, um den Workflow in den nächsten Zustand verschieben, wenn eine der Operationen aufgerufen wird. Dies versetzt in der Regel den Workflow in einen Zustand, in dem Sie verschiedene WCF-Operationen aufgerufen werden wartet. Wenn andererseits, soll näher Semantik dem parallel Modell, in denen alle Operationen aufgerufen werden muss jedoch nicht in einer bestimmten Reihenfolge, liegt dann nach jeder Aktivität empfangen die Wahl von Status nicht ändern oder mit die SetState-Aktivität für den Übergang den gleichen Zustand einen Übergang.
Diese letzte Option ist nicht ganz wie das Modell Parallel-Aktivität in einer potenziell bedeutende Weise. Mit der Aktivität parallel nach eine Operation aufgerufen wurde, kann nicht es erneut aufgerufen werden, wenn irgendwo nach die Parallel-Aktivität modelliert. Nachdem der Vorgang aufgerufen wird, wenn der Workflow in demselben Zustand bleibt, kann es im Modell Computer Zustand Nachrichten für andere Vorgänge oder den ursprünglichen Vorgang empfangen. Wirksam, der Status kann bieten Ihnen Semantik ähnelt eine Listen-Aktivität in einer While-Aktivität, warten auf alle Ereignisse, reagieren auf ein einzelnes Ereignis Schleife zurück und die gleichen Ereignisse erneut warten.

Senden Sie Ihre Fragen und Kommentare zu mmnet30@microsoft.com.

Matt Milner ist ein Mitglied des technischen Personals bei Pluralsight, wo er auf verbundene Systeme Technologien (WCF, Windows Workflow, BizTalk, „ Dublin „, konzentriert sichund die Azure Services). Matt ist ebenfalls ein unabhängiger Berater spezialisiert Microsoft.NET Anwendung entwerfen und entwickeln. Matt nutzt seine Liebe Technologie regelmäßig durch hält Vorträge auf lokale, regionale und internationale Konferenzen wie Tech. Ed. Microsoft hat Matt als MVP für seine Community Beiträge um Technologie verbundenen Systemen erkannt. Erreichen Sie Matt über seinen Blog: pluralsight.com/community/blogs/matt/.

Page view tracker