microsoft press windows workflow foundation step by step phần 4 ppt

36 414 0
microsoft press windows workflow foundation step by step phần 4 ppt

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Chapter 6 Loading and Unloading Instances 105 6. If you expand the Databases node in Object Explorer, you should find the new WorkflowStore database has been added. 7. Next we’ll need to execute the scripts I mentioned that .NET 3.0 provides for persistence, starting with the schema script. As before, the scripts are located in <%WINDIR%>\Microsoft.NET\Framework\v3.0\Windows Workflow Founda- tion\SQL\EN, where <%WINDIR%> is your Windows directory (typically, C:\Win- dows). From SQL Server Management Studio’s File menu, select Open and then File, which brings up the common Open File dialog box. Using the controls in the Open File dialog box, locate the schema script, SqlPersistenceService_Schema.sql. Select that from the available scripts, and click the Open button. Note that you’ll need to connect to your database server once again. 106 Part I Introducing Windows Workflow Foundation (WF) 8. SQL Server Management Studio will load the script into a new window, but before we actually run the script, remember we’ll need to specify which database we want the script to run against. Of course, we want to use the WorkflowStore database we just created. Therefore, locate the WorkflowStore database in the drop-down list of databases and select it as the target. 9. With the WorkflowStore database designated as the target of the script, execute the script by clicking the Execute button on the toolbar. 10. Repeat steps 7 through 9 to execute the SqlPersistenceService_Logic.sql script. This loads the necessary stored procedures into the database. If everything worked as it should, we now have a database ready for workflow instance storage. It’s time to plug SqlWorkflowPersistenceService into our workflow processing so that we can use the database we just created. Introducing the SqlWorkflowPersistenceService Service If it becomes necessary to persist an executing workflow, something must actually perform the persistence action. However, saving and restoring workflow instances is optional—you don’t have to shuffle workflow instances off to a durable storage medium (such as a database) if you don’t want to. So it probably makes sense that persistence is implemented by a pluggable service, SqlWorkflowPersistenceService. WorkflowInstance works in concert with Chapter 6 Loading and Unloading Instances 107 SqlWorkflowPersistenceService if the service is present when the workflow instance is running to perform the save and restore tasks. On the surface, this all sounds relatively simple. If we need to swap a workflow instance out to the database, we just tell the persistence service to save it for us. But what happens if we’re using a single database to persist workflows running in different processes? How do workflow instances actually stop and restart in the middle of their execution? It’s not uncommon for there to be a single database used for storing workflow instances. But each instance might have been executing on different machines and possibly within different processes on any given machine. If a workflow instance is saved and later restored, we must have a way to also restore the system state that was in effect at the time the workflow instance was executing. For example, SqlWorkflowPersistenceService stores whether or not the instance was blocked (waiting for something), its execution status (executing, idle, and so on), and var- ious and sundry informational items such as serialized instance data and the owner identifier. All this information is necessary to rehydrate the instance at a later time. We can control this persistence via the WorkflowInstance object through three methods, shown in Table 6-1. As Table 6-1 indicates, we have two methods available for unloading and persisting a work- flow instance. Which method you use depends on what you intend for your code to do. Unload waits for the workflow instance to become ready to be persisted. If this takes a long time, the thread executing the Unload operation also waits a long time. However, TryUnload will return immediately when asked to unload an executing workflow instance. But there is no guarantee the workflow instance actually unloaded and persisted to the database. To check for that, you should examine the return value from TryUnload. If the value is true, the work- flow instance did unload and persist itself. If the value is false, the workflow instance didn’t unload and persist. The advantage of TryUnload is that your thread isn’t sitting there waiting. The disadvantage, or course, is that you might have to repeatedly use TryUnload to force out the executing workflow instance. Table 6-1 WorkflowInstance Methods, Revisited Method Purpose Load Loads a previously unloaded (persisted) workflow instance. Tr yUnload Tries to unload (persist) the workflow instance from memory. Unlike calling Unload, calling Tr yUnload will not block (hold up execution) if the workflow instance cannot be immediately unloaded. Unload Unloads (persists) the workflow instance from memory. Note that this method blocks the currently executing thread that made this unload request until the workflow instance can actually unload. This can be a lengthy operation, depending on the individual workflow task. 108 Part I Introducing Windows Workflow Foundation (WF) Unloading Instances Although there are specific times WF will unload and persist your workflow instance, in some cases you might want to take control of that yourself. For those situations, WorkflowInstance.Unload and WorkflowInstance.TryUnload are there to help. If you call either of these methods without first plugging in the SqlWorkflowPersistenceService, WF will throw an exception. Of course, if there is a database error of some kind, you’ll also receive an exception. Therefore, it’s good practice to wrap these calls in try/catch blocks to keep from crashing your entire application. (Note that’s not to say you have to do anything with the exception sometimes you may just want to ignore it.) Let’s try it out! In fact, let’s build a small graphical user interface that provides us with buttons we can use to force specific application behavior. The application complexity will increase a little, but we’ll also be moving toward more realistic applications. The application we’ll build here is still relatively simple-minded. It will have only a few buttons we can click at specific times to force a workflow instance to unload. (In the next section, we’ll then load it again.) I’m going to intentionally force a long-running workflow, but unlike the workflows we’ve seen so far, it won’t use a Delay activity. The reason for this, as you probably guessed, is simply that Delay activities are special and come with persistence abilities of their own. Instead, I want to force our workflow instance to unload rather than have it automati- cally unload as a Delay activity could do. We’ll look at Delay activities and their abilities in the “Loading and Unloading Instances on Idle” section of this chapter. For this application, I’ll ask the workflow thread to sleep for 10 seconds to give us plenty of time to push one of our application’s buttons. Create a new host application 1. As you have in the previous chapters, open Visual Studio to create a new application project. However, instead of creating a console-based application, select instead a Windows-based application. Name it WorkflowPersister. Be sure to create the application in \Workflow\Chapter6. Follow the steps from Chapter 2 described in “Adding the workflow assembly references”, “Hosting the workflow runtime” (add code to the Main method following the call to Application.Run), “Creating the WorkflowRuntime factory object”, “Starting the workflow runtime,” “Stopping the workflow runtime,” “Using the workflow runtime factory object,” and “Handling workflow runtime events” procedures. Finally, add an app.config file following steps 1 and 2 from the previous chapter in “Add SqlTrackingService to your workflow.” (Don’t forget to add a reference to System.Configuration.) Chapter 6 Loading and Unloading Instances 109 2. Now add the proper connection string to app.config, one that reflects the database we’ll be using (remember, the database is called WorkflowStore). Keep in mind that the connectionString attribute in the add XML element presented here is to be applied as a single line in the app.config file. Printable line length limitations prevent this from being shown as a single line. <connectionStrings> <add name="StorageDatabase" connectionString="Data Source=(local)\SQLEXPRESS; Initial Catalog=WorkflowStore;Integrated Security=True;"/> </connectionStrings> 3. When you created the WorkflowPersister project, Visual Studio displayed the Windows Forms visual designer. The preceding step took you to the code editor, where you modified app.config. Return now to the Windows Forms visual designer by selecting Form1.cs in Solution Explorer and clicking the View Designer toolbar button. In a man- ner similar to designing workflows, this visual designer allows you to drag and drop Windows controls onto the design surface to customize their properties and hook their events. For now, move the mouse to the Toolbox, select a Button control, and drag it onto the designer’s surface. 110 Part I Introducing Windows Workflow Foundation (WF) Then drop it to insert the button into your form. 4. We’ll want to assign some meaningful text to the button so that we know what we’re clicking. (The control text “button1” just isn’t descriptive enough!) With the button highlighted (the little squares showing), select the button’s Text property in the Visual Studio Properties pane and change the text value to Start Workflow. Chapter 6 Loading and Unloading Instances 111 Note In general it is a good idea to also rename the variable names Visual Studio assigns to the controls. If you have many controls on your form, pretty soon auto- generated names such as “button1” become meaningless from a coding perspective. I won’t worry about that here because we’ll have few controls to deal with, but in any real-world application you should change the control names to useful values. For this example, leave the variable names as Visual Studio assigned them so that you won’t have to translate variable names while typing the code I’m about to present. 5. As you might expect, we’ll want to take some action when the button is clicked. To do that, we’ll need to inject a button click handler. While in the Properties pane, click the Events toolbar button (the lightning bolt) and double-click the Click event to add a click event handler. Visual Studio will automatically switch you to the code view, so return to the designer for the next step. We’ll add code to the event handler in a later step. 6. The text we added will most likely be too wide for the button as Visual Studio created it, so we’ll want to stretch the button to be a bit wider. To do so, click the button on the designer’s surface (if it’s not activated already) and drag the rightmost square to the right to stretch the button’s width. 112 Part I Introducing Windows Workflow Foundation (WF) 7. Repeat steps 3 through 5 to add two more buttons, one with the text Unload Workflow and the other with the text Load Workflow. (No need to change the variable names for this simple example.) 8. Our user interface is now visually established for our workflow testing purposes. Now it’s time to code some internal application processes we’ll execute in response to appli- cation events. We’ll need to initialize some things when the application loads, and a great place to do that is in the Load event handler for the main application form. Click the title bar of the form in the visual editor to activate the form’s properties. Click the Events button (as you did for the three button controls), and double-click the Load event to insert a Load event handler. Chapter 6 Loading and Unloading Instances 113 9. Once the load event handler is inserted, Visual Studio will switch you to the code view for the main application form. Because we just added the form’s Load event handler, we might as well add the initialization code we’ll need. Type the following into the Form1_Load handler method: _runtime = WorkflowFactory.GetWorkflowRuntime(); _runtime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(Runtime_WorkflowCompleted); _runtime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs>(Runtime_WorkflowTerminated); We’ve seen code like this before that creates the workflow runtime and hooks some of the major events we’ll be interested in intercepting. 10. Somewhere we need to declare the _runtime field, so look for the opening brace for the Form1 class. After the opening brace, type this: protected WorkflowRuntime _runtime = null; protected WorkflowInstance _instance = null; 11. If you try to compile the application at this point, it won’t compile. We’ll need to add a reference to the Windows Workflow Foundation assemblies as we’ve done in previous chapters—that process is the same whether we’re building a graphical user interface or a console-based application. So add the workflow assembly references for System.Workflow.Runtime, System.Workflow.ComponentModel, and System.Workflow.Activ- ity and then insert the following using declaration at the top of the source file following the other using declarations: using System.Workflow.Runtime; 12. Although we now have an application that hosts the workflow runtime, it doesn’t actu- ally do anything. To make it functional, we’ll need to add some code to the button event handlers, starting with button1_Click. Scroll through the main application form’s source file until you find button1_Click, and add this code: button2.Enabled = true; button1.Enabled = false; _instance = _runtime.CreateWorkflow(typeof(PersistedWorkflow.Workflow1)); _instance.Start(); 114 Part I Introducing Windows Workflow Foundation (WF) This code disables the Start Workflow button, enables the Unload Workflow button, and then starts a new workflow instance. (We’ll add the workflow that it will execute shortly.) 13. Next, find the Unload Workflow button’s handler, button2_Click, and add the following code. Here, we’re using the WorkflowInstance.Unload method to unload the workflow instance and write it to our database. After the workflow instance unloads, we enable the Load Workflow button (the code for which we’ll add in the next section). Note that if we sustain an exception while unloading the workflow instance, the Load Workflow button is not enabled. This makes sense there would be nothing to load if the unload request failed. button2.Enabled = false; try { _instance.Unload(); button3.Enabled = true; } // try catch (Exception ex) { MessageBox.Show(String.Format("Exception while unloading workflow" + " instance: '{0}'",ex.Message)); } // catch Note I mentioned this previously in the chapter, but it’s an important point. Keep in mind that WorkflowInstance.Unload is synchronous. That means the thread making the attempt to unload the workflow instance will block (wait) and continue to be blocked until the operation has completed (the instance has unloaded or failed to unload). In this case, that’s precisely the behavior I want because I don’t want to repeatedly ask the instance whether it unloaded. But in some cases, you’ll want to use the nonblock- ing alternative I mentioned, WorkflowInstance.TryUnload. Later, when you add the final pieces of code and run this application, as you click Unload Workflow, watch closely and you’ll see the application freeze briefly as it waits for the workflow to unload. 14. Now we turn our attention to the workflow event handlers, Runtime_WorkflowCompleted and Runtime_WorkflowTerminated. Both of these event handlers will actually perform the same action, which is to reset the application in preparation for another workflow instance execution. Add these methods following the click event handler for button2 (the method containing the code we added in the preceding step): void Runtime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e){ WorkflowCompleted(); } void Runtime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e) { WorkflowCompleted(); } [...]... for workflow completion."); Chapter 6 Loading and Unloading Instances 123 12 Of course, the application isn’t waiting for workflow completion since no workflow was started To create a workflow instance, add this code following the line of code you just located: // Create the workflow instance WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(IdledWorkflow .Workflow1 )); // Start the workflow. .. \Workflow\ Chapter6 Follow the steps from Chapter 2 in the Adding the workflow assembly references,” “Hosting the workflow runtime,” “Creating the WorkflowRuntime factory object,” “Starting the workflow runtime,” “Stopping the workflow runtime,” “Using the workflow runtime factory object,” and “Handling workflow runtime events” procedures 2 Modify the WorkflowFactory class as you did in steps 16 and 17 of the... and the SqlWorkflowPersistenceService_Logic.sql script 1 24 Part I Introducing Windows Workflow Foundation (WF) To Do This Use the SqlWorkflowPersistenceService After creating an instance of WorkflowRuntime but before you call its StartRuntime method, add a new instance of SqlWorkflowPersistenceService to the runtime services using WorkflowRuntime.AddService Manually unload and persist a workflow instance... instance of WorkflowPersister and click the Load Workflow button The Load Workflow button will then become disabled, while the Start Workflow button will become enabled 6 Close the WorkflowPersister application by clicking the X in the upper right corner or pressing Alt+F4 The application will shut down 7 The Visual Studio Output window should now contain information regarding the two workflows we... the same) Follow Steps 1 and 2 from the “Add SqlTrackingService to your workflow procedure in Chapter 5 regarding adding the app.config file 122 Part I Introducing Windows Workflow Foundation (WF) 5 Create a separate sequential workflow library project as you did in Chapter 3 to house our new workflow (See the section in Chapter 3 entitled “Adding a sequential workflow project to the WorkflowHost solution.”)... menu 2 Click the Start Workflow button to create and start a workflow instance The Start Workflow button should become disabled, while the Unload Workflow button will be enabled Because we told the workflow thread to sleep for 10 seconds, after 10 seconds has elapsed the Unload Workflow button should disable itself and the Start Workflow button should be re-enabled In this test, the workflow ran to completion,... a sequential workflow project to the WorkflowHost solution.”) Name this workflow library IdledWorkflow 6 Repeat step 2 and then steps 4 through 6 from the previous example, in the section entitled “Create a new unloadable workflow. ” This places two Code Activities in your workflow 7 Adding the second Code Activity in the last step will take you to the Visual Studio code editor While there, add this... the tracking service to the workflow runtime With some minor adjustments, that same code works here We’ll change the service from SqlTrackingService to SqlWorkflowPersistenceService and change the using statement (from System .Workflow. Runtime.Tracking to System .Workflow. Runtime.Hosting) Open the WorkflowFactory.cs file for editing 116 Part I Introducing Windows Workflow Foundation (WF) 17 Instead of... persisted workflows in your database! Chapter 6 Quick Reference To Do This Create the workflow persistence database After creating a new database for the task, execute within SQL Server Management Studio Express the SQL scripts you find in the \Microsoft. NET\Framework\v3.0 \Windows Workflow Foundation\ SQL\EN directory within SQL Server Management Studio You’ll need to execute both the SqlWorkflowPersistenceService_Schema.sql... to create a workflow instance from the PersistedWorkflow .Workflow1 type (in step 12), our host application won’t compile and execute We’ll take care of that in the following section There you have it! A Windows graphical user interface and host application we can use to house our workflow Speaking of workflow, shouldn’t we create one to execute? In fact, that’s next Create a new unloadable workflow 1 . _runtime.CreateWorkflow(typeof(PersistedWorkflow .Workflow1 )); _instance.Start(); 1 14 Part I Introducing Windows Workflow Foundation (WF) This code disables the Start Workflow button, enables the Unload Workflow. WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(IdledWorkflow .Workflow1 )); // Start the workflow instance. instance.Start(); 13. Compile the solution by pressing F6. Correct any. both the SqlWorkflowPersistenceService_Schema.sql script and the SqlWorkflowPersistenceService_Logic.sql script. 1 24 Part I Introducing Windows Workflow Foundation (WF) Use the SqlWorkflowPersistenceService

Ngày đăng: 06/08/2014, 02:20

Từ khóa liên quan

Mục lục

  • Part I: Introducing Windows Workflow Foundation (WF)

    • Chaper 6: Loading and Unloading Instances

      • Introducing the SqlWorkflowPersistenceService Service

      • Unloading Instances

      • Loading Instances

      • Loading and Unloading Instances on Idle

      • Chapter 6 Quick Reference

      • Part II: Working with Activities

        • Chaper 7: Basic Activity Operations

          • Using the Sequence Activity Object

          • Using the Code Activity

          • Using the Throw Activity

          • Using the FaultHandler Activity

            • Quick Tour of the Workflow Visual Designer

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan