Download as pdf
Download as pdf
You are on page 1of 6
How to: Cancel a Dataflow Block ‘This document demonstrates how to enable cancellation in your application. This example uses Windows Forms to show where work items are active in a dataflow pipeline and also the effects of cancellation, The TPL Dataflow Library (System. Threading Tasks Dataflow namespace) is not distributed with the NET Framework 4.5. To install the System Threading Tasks.Dataflow namespace, open your project in Visual Studio 2012, choose Manage NuGet Packages from the Project menu, and search online for the Microsoft. Tpl.Dataflow package. To Create the Windows Forms Application 1. Create a C# or Visual Basic Windows Forms Application project. In the following steps, the project is named CancellationWinForns. 2. On the form designer for the main form, Form1.cs (Form/.vb for Visual Basic), add a ToolStrip control 3, Add a Too!StripButton control to the ToolStrip control, Set the DisplayStyle property t Work Items, ‘Text and the Text property to Add 4, Add a second ToolStripButton control to the ToolStrip control, Set the DisplayStyle property to Text, the Text property to Cancel, and the Enabled property to False. 5, Add four ToolstripProgressBar objects to the ToolStrip control Creating the Dataflow Pipeline This section describes how to create the dataflow pipeline that processes work items and updates the progress bars To Create the Dataflow Pipeline 1. In your project, add a reference to System.Threading Tasks Dataflow. 2. Ensure that Form1.cs (Form1.vb for Visual Basic) contains the following using statements (Inport in Visual Basic) VB Imports Systen. Threading Imports Systen. Threading. Tasks Imports Systen.Threading.Tasks.Dataflow 3. Add the WorkItem class as an inner type of the Formd class, vB "A placeholder type that performs work. Private Class WorkItem * Performs work for the provided nunber of milliseconds. Public Sub DoWork(8yVal milliseconds As Integer) * For demonstration, suspend the current thread. Thread.Sleep(milliseconds) End Sub End Class hnpssimsch microsoft comen-ustibraryinh228611 (printer v=vs.110) aspx 16 220017 How to: Cancel @ Datatow Block 4, Add the following data members to the Form! class. vB Enables the user interface to signal cancellation. Private cancellationSource As CancellationTokenSource The first node in the dataflow pipeline. Private startWork As TransformBlock(Of WorkIten, WorkTten) The second, and final, node in the dataflow pipeline. Private completeWork As ActionBlock(Of WorkIten) "Increments the value of the provided progress bar. Private increnentProgress As ActionBlock(Of ToolstripProgressBar) Decrements the value of the provided progress bar. Private decrenentProgress As ActionBlock(Of ToolStripProgressBar) * Enables progress bar actions to run on the UI thread. Private uiTaskScheduler As TaskScheduler 5. Add the following method, CreatePipeline, to the Form class. (ve | * Creates the blocks that participate in the dataflow pipeline. Private Sub CreatePipeline() " Create the cancellation source. cancellationSource = New CancellationTokenSource() * Create the first node in the pipeline. starthork = New TransformBlock(Of WorkItem, WorkTtem) (Function(workTtem) * Perform some work. * becrement the progress bar that tracks the count of * active work itens in this stage of the pipeline. "Increment the progress bar that tracks the count of * active work itens in the next stage of the pipeline. " Send the work iten to the next stage of the pipeline. workItem.DoWork(25@) decrenentProgress.Post(toolStripProgressfar1) increnentProgress.Post (toolStripProgressBar2) Return workTtem cancel lationSource. Token}) Create the second, and final, node in the pipeline. conpleteWork = New ActionBlock(Of WorkItem) (Sub(workIten) Perform sone work. Decrement the progress bar that tracks the count of active work itens in this stage of the pipeline. " Increment the progress bar that tracks the overall count of completed work itens. workItem.Doviork(1000) decrenentProgress .Post(toolstripProgressBar2) increnentProgress .Post (toolStripProgressBar3) End Sub, New ExecutionDataflowBlockOptions With { .CancellationToken cancellationSource.Token, .MaxDegreeOfParallelism = 2 }) * Connect the two nodes of the pipeline. starthork.LinkTo(conpleteWork) ‘When the first node completes, set the second node also to * the completed state. starthork.Conpletion.Continuedith(sub() conpleteWork.Complete()) * Create the dataflow action blocks that increnent and decrement * progress bars. * These blocks use the task scheduler that is associated with * the UI thread. hnps:imsch microsoft comen-ustibraryinh228611 (printer v=vs.110) aspx End Function, New ExecutionDataflowBlockoptions With {.CancellationToken = 220017 How to: Cancel @ Datatow Block increnentProgress = New ActionBlock(Of ToolStripProgressBar) (Function(progressBar) Math.Max(Interlocked. Increnent (progressBar.Value), progressBar.Value - 1), New ExecutionDataflowBlockOptions With {.CancellationToken cancellationSource.Token, .TaskScheduler = uiTaskScheduler}) decrementProgress = New ActionBlock (OF ToolStripProgressBar) (Function(progressBar) Math.Max(Interlocked.Decrenent (progressBar.Value), progressBar.Value), New ExecutionDataflowBlockOptions With {.CancellationToken = cancellationSource. Token, .TaskScheduler = uitaskScheduler}) End Sub Because the increnentProgress and decrenentProgress dataflow blocks act on the user interface, itis important that actions occur on the user-interface thread. To accomplish this, during construction these objects each provide a ExecutionDataflowBlockOptions object that has the TaskScheduler property set to ‘TaskScheduler. FromCurrentSynchronizationContext. The TaskScheduler.FromCurrentSynchronizationContext method creates a ‘TaskScheduler object that performs work on the current synchronization context. Because the Formt constructor is called from ‘the user-interface thread, the actions for the increnentProgress and decrementProgress dataflow blocks also run on the user-interface thread, This example sets the CancellationToken property when it constructs the members of the pipeline. Because the CancellationToken property permanently cancels dataflow block execution, the whole pipeline must be recreated after the user cancels the operation and then wants to add more work items to the pipeline. For an example that demonstrates an alternative way to cancel a dataflow block so that other work can be performed after an operation is canceled, see Walkthrough: Using Dataflow in a Windows Forms Application. Connecting the Dataflow Pipeline to the User Interface ‘This section describes how to connect the dataflow pipeline to the user interface. Both creating the pipeline and adding work items to the pipeline are controlled by the event handler for the Add Work Items button. Cancellation is initiated by the Cancel button. When the user clicks either of these buttons, the appropriate action is initiated in an asynchronous manner. ‘To Connect the Dataflow Pipeline to the User Interface 1. On the form designer for the main form, create an event handler for the Click event for the Add Work Items button, 2. Implement the Click event for the Add Werk Items button, [| " Event handler for the Add Work Itens button. Private Sub toolStripButtont_Click(SyVal sender As Object, ByVal e As EventArgs) Handles toolstripButton1 .Click "The Cancel button is disabled when the pipeline is not active. ‘ Therefore, create the pipeline and enable the Cancel button + Af the Cancel button is disabled. If Not toolStripButton2.Enabled Then CreatePipeline() * Enable the Cancel button. toolstripButton2. Enabled = True End If * Post several work items to the head of the pipeline. For 4 As Integer = @ To 4 toolstripProgressBart.Value += 1 starthork.Post(New WorkItem()) Next i End Sub 3.On the form designer for the main form, create an event handler for the Click event handler for the Cancel button. 4, Implement the Click event handler for the Caneel button, (we | hnps:imsch microsoft comen-ustibraryinh228611 (printer v=vs.110) aspx 36 220017 How to: Cancel @ Datatow Block Event handler for the Cancel button. Private Async Sub toolStripButton2_Click(ByVal sender As Object, ByVal @ As EventArgs) Handles toolStripButton2.Click Disable both buttons. toolStripButton1.Enabled = False toolStripButton2.Enabled = False * Trigger cancellation. cancellationSource.Cancel() Try Asynchronously wait for the pipeline to complete processing and for * the progress bars to update. Await Task.WhenAll(completeWork.Completion, increnentProgress.Conpletion, decrenentProgress .Conpletion) Catch e1 As OperationCanceledException End Try * Increment the progress bar that tracks the number of cancelled ‘work items by the number of active work items. toolStripProgressBar4.Value += toolStripProgressBarl.Value toolStripProgressBard.Value += toolStripProgressBar2.Value "Reset the progress bars that track the number of active work items toolstripProgressBari.Value = @ toolstripProgressBar2.Value = @ * Enable the Add Work Items button. toolStripButton1.Enabled = True End Sub Example ‘The following example shows the complete code for Formt.cs (Form!.vb for Visual Basic) vB Imports System. Threading Imports Systen. Threading. Tasks Imports System. Threading. Tasks.Dataflow Namespace CancellationWinForms Partial Public Class Form Inherits Form "A placeholder type that performs work. Private Class WorkTtem " Perforns work for the provided number of milliseconds. Public Sub DoWork(ByVal milliseconds As Integer) * For demonstration, suspend the current thread. Thread. Sleep (milliseconds) End sub End Class * Enables the user interface to signal cancellation. Private cancellationSource As CancellationTokenSource ‘The first node in the dataflow pipeline. Private startWork As TransformBlock(Of WorkItem, WorkIten) The second, and final, node in the dataflow pipeline. Private completeWiork As ActionBlock (Of WorkItem) "Increments the value of the provided progress bar. Private increnentProgress As ActionBlock(OF ToolStripProgressBar) " Decrenents the value of the provided progress bar Private decrenentProgress As ActionBlock(Of ToolStripProgressBar) Inipssimsch microsoft comen-ustibraryhh 228611 (printer v=vs.110) aspx s22n017 How to: Cancel @ Datatow Block * Enables progress bar actions to run on the UI thread. Private uiTaskScheduler As TaskScheduler Public Sub New() InitializeComponent() " Create the UI task scheduler from the current sychronization * context. uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext () End sub * Creates the blocks that participate in the dataflow pipeline. Private Sub CreatePipeline() Create the cancellation source cancellationSource = New CancellationTokenSource() " Create the first node in the pipeline. starthiork = New TransfornBlock(OF WorkItem, WorkIten) (Function(workIten) Perform sone work. Decrenent the progress bar that tracks the count of active work items in this stage of the pipeline. Increment the progress bar that tracks the count of active work itens in the next stage of the pipeline "Send the work item to the next stage of the pipeline. workItem. DoWork(250) decrenentProgress Post (toolStripProgressBar1) increnentProgress.Post(toolstripProgressBar2) Return workTten End Function, New ExecutionDataflowBlockoptions With {.CancellationToken cancellationSource. Token}) " create the second, and final, node in the pipeline. conpleteWiork = New ActionBlock(OF WorkItem) (Sub(workItem) * Perform sone work. Decrement the progress bar that tracks the count of active work items in this stage of the pipeline. Increment the progress bar that tracks the overall count of completed work items. workTten.DoWork( 1008) decrenentProgress.Post(toolStripProgressBar2) increnentProgress.Post (toolStripProgressBar3) End Sub, New ExecutionDataflow8lockoptions with { .CanceLlationToken = cancellationSource.Token, .MaxDegreeOfParallelism = 2 }) " Connect the two nodes of the pipeline. starthiork. LinkTo (completeWork) “When the first node completes, set the second node also to "the completed state. starthork.Completion.ContinueWith(Sub() completework.Conplete()) Create the dataflow action blocks that increment and decrenent progress bars. These blocks use the task scheduler that is associated with ‘the UI thread. increnentProgress = New ActionBlock(Of ToolStripProgressBar) (Function(progressBar) Math.Max(Interlocked. Increment (progressBar.Value), progress6ar.Value - 1), New ExecutionDataflowBlockOptions With {.CancellationToken = cancellationSource.Token, sTaskScheduler = uiTaskScheduler}) decrementProgress = New ActionBlock(Of ToolStripProgressBar) (Funct ion(progressBar) Math.Max(Interlocked.Decrement(progress#ar.Value), progressBar.Value), New ExecutionDataflowBlockOptions with {.CancellationToken = cancellationSource. Token, -TaskScheduler = uiTaskScheduler}) End sub * Event handler for the Add Work Items button. Private Sub toolstripautton1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles toolstripButtond.Click " The Cancel button is disabled when the pipeline is not active. ‘Therefore, create the pipeline and enable the Cancel button "Gf the Cancel button is disabled. If Not toolstripButton2. Enabled Then Inipssimsch microsoft comen-ustibraryhh 228611 (printer v=vs.110) aspx s22n017 How to: Cancel @ Datatow Block CreatePipeline() * Enable the Cancel button. toolstripButton2. Enabled = True End If * Post several work itens to the head of the pipeline. For i As Integer = @ To 4 toolstripProgressBar1.Value += 1 starthork.Post(New WorkItem()) Next 1 End sub * Event handler for the Cancel button. Private Asyne Sub toolstripButton2_Click(ByVal sender As Object, ByVal e As EventArgs) Handles toolstripButton2.click " Disable both buttons. ‘toolStripButtont. Enabled ‘toolStripButton?. Enabled False False "Trigger cancellation. cancellationSource.Cancel() Try " asynchronously wait for the pipeline to complete processing and for "the progress bars to update. ‘Await Task.whenAll (completeNork.Conpletion, incrementProgress.Completion, decrenentProgress.Conpletion) Catch e1 As OperationCanceledexception End Try "Increment the progress bar that tracks the number of cancelled "work items by the number of active work itens. toolStripProgressBar4.Value += toolStripProgressBar1.Value toolStripProgressBar4.Value += toolStripProgressBar2.Value " Reset the progress bars that track the number of active work itens. toolstripProgresssar1.Value = @ toolstripProgressBar2.Value = @ " Enable the Add Work Items button. toolStripButtoni.Enabled = True End sub Protected Overrides Sub Finalize() cancellationSource.Dispose() MyBase.Finalize() End sub End Class End Namespace ‘The following illustration shows the running application, Form hoses ‘Add Workitems Cancel ml rl = —_ Robust Programming See Also Dataflow © 2017 Microsoft hnpssimsch microsoft comen-ustibraryinh228611 (printer v=vs.110) aspx

You might also like