Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ez a dokumentum bemutatja, hogyan engedélyezheti a lemondást az alkalmazásban. Ez a példa a Windows Forms használatával mutatja be, hogy hol aktívak a munkaelemek egy adatfolyam-folyamatban, valamint a lemondás hatásait.
Feljegyzés
A TPL-adatfolyamtár (a System.Threading.Tasks.Dataflow névtér) nincs elosztva a .NET-tel. Ha telepíteni szeretné a névteret a System.Threading.Tasks.Dataflow Visual Studióban, nyissa meg a projektet, válassza a Project menü NuGet-csomagok kezelése parancsát, és keressen rá online a System.Threading.Tasks.Dataflow csomagra. Másik lehetőségként futtassa dotnet add package System.Threading.Tasks.Dataflowa .NET Core parancssori felülettel való telepítéshez.
A Windows Forms alkalmazás létrehozása
C# vagy Visual Basic Windows Forms-alkalmazásprojekt létrehozása. A következő lépésekben a projekt neve .
CancellationWinFormsA főűrlap űrlaptervezőjében Form1.cs (a Visual Basic Form1.vb) adjon hozzá egy vezérlőt ToolStrip .
Adjon hozzá egy vezérlőt ToolStripButton a ToolStrip vezérlőhöz. Állítsa be a DisplayStyle tulajdonságot és Text a Text tulajdonságot munkaelemek hozzáadására.
Adjon hozzá egy második ToolStripButton vezérlőt a ToolStrip vezérlőhöz. Állítsa be a DisplayStyle tulajdonságot Texta Text Mégse értékre, a tulajdonságot pedig a Enabled következőre
False.Adjon hozzá négy ToolStripProgressBar objektumot a ToolStrip vezérlőhöz.
Az adatfolyam-folyamat létrehozása
Ez a szakasz azt ismerteti, hogyan hozhatja létre a munkaelemeket feldolgozó adatfolyam-folyamatot, és hogyan frissítheti a folyamatjelző sávokat.
Az adatfolyam-folyamat létrehozása
A projektben adjon hozzá egy hivatkozást a System.Threading.Tasks.Dataflow.dll.
Győződjön meg arról, hogy a Form1.cs (a Visual Basic Form1.vb) tartalmazza a következő
usingirányelveket (Importsa Visual Basicben).using System; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; using System.Windows.Forms;Imports System.Threading Imports System.Threading.Tasks Imports System.Threading.Tasks.DataflowAdja hozzá az
WorkItemosztályt azForm1osztály belső típusaként.// A placeholder type that performs work. class WorkItem { // Performs work for the provided number of milliseconds. public void DoWork(int milliseconds) { // For demonstration, suspend the current thread. Thread.Sleep(milliseconds); } }' A placeholder type that performs work. Private Class WorkItem ' Performs 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 ClassAdja hozzá a következő adattagokat az
Form1osztályhoz.// Enables the user interface to signal cancellation. CancellationTokenSource cancellationSource; // The first node in the dataflow pipeline. TransformBlock<WorkItem, WorkItem> startWork; // The second, and final, node in the dataflow pipeline. ActionBlock<WorkItem> completeWork; // Increments the value of the provided progress bar. ActionBlock<ToolStripProgressBar> incrementProgress; // Decrements the value of the provided progress bar. ActionBlock<ToolStripProgressBar> decrementProgress; // Enables progress bar actions to run on the UI thread. TaskScheduler uiTaskScheduler;' Enables the user interface to signal cancellation. Private cancellationSource As CancellationTokenSource ' The first node in the dataflow pipeline. Private startWork As TransformBlock(Of WorkItem, WorkItem) ' The second, and final, node in the dataflow pipeline. Private completeWork As ActionBlock(Of WorkItem) ' Increments the value of the provided progress bar. Private incrementProgress As ActionBlock(Of ToolStripProgressBar) ' Decrements the value of the provided progress bar. Private decrementProgress As ActionBlock(Of ToolStripProgressBar) ' Enables progress bar actions to run on the UI thread. Private uiTaskScheduler As TaskSchedulerAdja hozzá a következő metódust
CreatePipelineazForm1osztályhoz.// Creates the blocks that participate in the dataflow pipeline. private void CreatePipeline() { // Create the cancellation source. cancellationSource = new CancellationTokenSource(); // Create the first node in the pipeline. startWork = new TransformBlock<WorkItem, WorkItem>(workItem => { // Perform some work. workItem.DoWork(250); // Decrement the progress bar that tracks the count of // active work items in this stage of the pipeline. decrementProgress.Post(toolStripProgressBar1); // Increment the progress bar that tracks the count of // active work items in the next stage of the pipeline. incrementProgress.Post(toolStripProgressBar2); // Send the work item to the next stage of the pipeline. return workItem; }, new ExecutionDataflowBlockOptions { CancellationToken = cancellationSource.Token }); // Create the second, and final, node in the pipeline. completeWork = new ActionBlock<WorkItem>(workItem => { // Perform some work. workItem.DoWork(1000); // Decrement the progress bar that tracks the count of // active work items in this stage of the pipeline. decrementProgress.Post(toolStripProgressBar2); // Increment the progress bar that tracks the overall // count of completed work items. incrementProgress.Post(toolStripProgressBar3); }, new ExecutionDataflowBlockOptions { CancellationToken = cancellationSource.Token, MaxDegreeOfParallelism = 2 }); // Connect the two nodes of the pipeline. When the first node completes, // set the second node also to the completed state. startWork.LinkTo( completeWork, new DataflowLinkOptions { PropagateCompletion = true }); // Create the dataflow action blocks that increment and decrement // progress bars. // These blocks use the task scheduler that is associated with // the UI thread. incrementProgress = new ActionBlock<ToolStripProgressBar>( progressBar => progressBar.Value++, new ExecutionDataflowBlockOptions { CancellationToken = cancellationSource.Token, TaskScheduler = uiTaskScheduler }); decrementProgress = new ActionBlock<ToolStripProgressBar>( progressBar => progressBar.Value--, new ExecutionDataflowBlockOptions { CancellationToken = cancellationSource.Token, TaskScheduler = uiTaskScheduler }); }' 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. startWork = New TransformBlock(Of WorkItem, WorkItem)(Function(workItem) ' Perform some 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 count of ' active work items in the next stage of the pipeline. ' Send the work item to the next stage of the pipeline. workItem.DoWork(250) decrementProgress.Post(toolStripProgressBar1) incrementProgress.Post(toolStripProgressBar2) Return workItem End Function, New ExecutionDataflowBlockOptions With {.CancellationToken = cancellationSource.Token}) ' Create the second, and final, node in the pipeline. completeWork = New ActionBlock(Of WorkItem)(Sub(workItem) ' Perform some 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. workItem.DoWork(1000) decrementProgress.Post(toolStripProgressBar2) incrementProgress.Post(toolStripProgressBar3) End Sub, New ExecutionDataflowBlockOptions With {.CancellationToken = cancellationSource.Token, .MaxDegreeOfParallelism = 2}) ' Connect the two nodes of the pipeline. When the first node completes, ' set the second node also to the completed state. startWork.LinkTo( completeWork, New DataflowLinkOptions With {.PropagateCompletion = true}) ' Create the dataflow action blocks that increment and decrement ' progress bars. ' These blocks use the task scheduler that is associated with ' the UI thread. incrementProgress = New ActionBlock(Of ToolStripProgressBar)( Sub(progressBar) progressBar.Value += 1, New ExecutionDataflowBlockOptions With {.CancellationToken = cancellationSource.Token, .TaskScheduler = uiTaskScheduler}) decrementProgress = New ActionBlock(Of ToolStripProgressBar)( Sub(progressBar) progressBar.Value -= 1, New ExecutionDataflowBlockOptions With {.CancellationToken = cancellationSource.Token, .TaskScheduler = uiTaskScheduler}) End Sub
Mivel az incrementProgress decrementProgress adatfolyam-blokkok a felhasználói felületen működnek, fontos, hogy ezek a műveletek a felhasználói felület szálán történjenek. Ennek érdekében az építés során ezek az objektumok egy ExecutionDataflowBlockOptions olyan objektumot biztosítanak, amelynek tulajdonsága TaskScheduler.FromCurrentSynchronizationContexta TaskScheduler következő. A TaskScheduler.FromCurrentSynchronizationContext metódus létrehoz egy TaskScheduler objektumot, amely az aktuális szinkronizálási környezetben végez munkát. Mivel a Form1 konstruktor a felhasználói felületi szálból van meghívva, az incrementProgress decrementProgress adatfolyam-blokkok műveletei a felhasználói felület szálán is futnak.
Ez a példa beállítja a CancellationToken tulajdonságot, amikor a folyamat tagjait hozza létre. Mivel a CancellationToken tulajdonság véglegesen megszakítja az adatfolyamblokkok végrehajtását, a teljes folyamatot újra létre kell hozni, miután a felhasználó megszakította a műveletet, majd további munkaelemeket szeretne hozzáadni a folyamathoz. Egy olyan példa, amely egy adatfolyamblokk megszakításának alternatív módját mutatja be, hogy a művelet megszakítása után más munka is elvégezhető legyen, tekintse meg az alábbi útmutatót: Adatfolyam használata Windows Forms-alkalmazásban.
Az adatfolyam-folyamat csatlakoztatása a felhasználói felülethez
Ez a szakasz azt ismerteti, hogyan csatlakoztathatja az adatfolyam-folyamatot a felhasználói felülethez. A folyamat létrehozását és a munkaelemek a folyamathoz való hozzáadását a Munkaelemek hozzáadása gomb eseménykezelője szabályozza. A lemondást a Mégse gomb kezdeményezi. Amikor a felhasználó ezekre a gombokra kattint, a megfelelő művelet aszinkron módon indul el.
Az adatfolyam-folyamat csatlakoztatása a felhasználói felülethez
A főűrlap űrlaptervezőjében hozzon létre egy eseménykezelőt az Click eseményhez a Munkaelemek hozzáadása gombhoz.
Implementálja a Click Munkaelemek hozzáadása gomb eseményét.
// Event handler for the Add Work Items button. private void toolStripButton1_Click(object sender, EventArgs e) { // The Cancel button is disabled when the pipeline is not active. // Therefore, create the pipeline and enable the Cancel button // if the Cancel button is disabled. if (!toolStripButton2.Enabled) { CreatePipeline(); // Enable the Cancel button. toolStripButton2.Enabled = true; } // Post several work items to the head of the pipeline. for (int i = 0; i < 5; i++) { toolStripProgressBar1.Value++; startWork.Post(new WorkItem()); } }' Event handler for the Add Work Items button. Private Sub toolStripButton1_Click(ByVal 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 ' if 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 i As Integer = 0 To 4 toolStripProgressBar1.Value += 1 startWork.Post(New WorkItem()) Next i End SubA főűrlap űrlaptervezőjében hozzon létre egy eseménykezelőt a Click Mégse gomb eseménykezelőjének.
Click A Mégse gomb eseménykezelőjének implementálása.
// Event handler for the Cancel button. private async void toolStripButton2_Click(object sender, EventArgs e) { // 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, incrementProgress.Completion, decrementProgress.Completion); } catch (OperationCanceledException) { } // Increment the progress bar that tracks the number of cancelled // work items by the number of active work items. toolStripProgressBar4.Value += toolStripProgressBar1.Value; toolStripProgressBar4.Value += toolStripProgressBar2.Value; // Reset the progress bars that track the number of active work items. toolStripProgressBar1.Value = 0; toolStripProgressBar2.Value = 0; // Enable the Add Work Items button. toolStripButton1.Enabled = true; }' Event handler for the Cancel button. Private Async Sub toolStripButton2_Click(ByVal sender As Object, ByVal e 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, incrementProgress.Completion, decrementProgress.Completion) 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 += toolStripProgressBar1.Value toolStripProgressBar4.Value += toolStripProgressBar2.Value ' Reset the progress bars that track the number of active work items. toolStripProgressBar1.Value = 0 toolStripProgressBar2.Value = 0 ' Enable the Add Work Items button. toolStripButton1.Enabled = True End Sub
Példa
Az alábbi példa a Form1.cs teljes kódját mutatja be (Form1.vb a Visual Basichez).
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using System.Windows.Forms;
namespace CancellationWinForms
{
public partial class Form1 : Form
{
// A placeholder type that performs work.
class WorkItem
{
// Performs work for the provided number of milliseconds.
public void DoWork(int milliseconds)
{
// For demonstration, suspend the current thread.
Thread.Sleep(milliseconds);
}
}
// Enables the user interface to signal cancellation.
CancellationTokenSource cancellationSource;
// The first node in the dataflow pipeline.
TransformBlock<WorkItem, WorkItem> startWork;
// The second, and final, node in the dataflow pipeline.
ActionBlock<WorkItem> completeWork;
// Increments the value of the provided progress bar.
ActionBlock<ToolStripProgressBar> incrementProgress;
// Decrements the value of the provided progress bar.
ActionBlock<ToolStripProgressBar> decrementProgress;
// Enables progress bar actions to run on the UI thread.
TaskScheduler uiTaskScheduler;
public Form1()
{
InitializeComponent();
// Create the UI task scheduler from the current synchronization
// context.
uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
}
// Creates the blocks that participate in the dataflow pipeline.
private void CreatePipeline()
{
// Create the cancellation source.
cancellationSource = new CancellationTokenSource();
// Create the first node in the pipeline.
startWork = new TransformBlock<WorkItem, WorkItem>(workItem =>
{
// Perform some work.
workItem.DoWork(250);
// Decrement the progress bar that tracks the count of
// active work items in this stage of the pipeline.
decrementProgress.Post(toolStripProgressBar1);
// Increment the progress bar that tracks the count of
// active work items in the next stage of the pipeline.
incrementProgress.Post(toolStripProgressBar2);
// Send the work item to the next stage of the pipeline.
return workItem;
},
new ExecutionDataflowBlockOptions
{
CancellationToken = cancellationSource.Token
});
// Create the second, and final, node in the pipeline.
completeWork = new ActionBlock<WorkItem>(workItem =>
{
// Perform some work.
workItem.DoWork(1000);
// Decrement the progress bar that tracks the count of
// active work items in this stage of the pipeline.
decrementProgress.Post(toolStripProgressBar2);
// Increment the progress bar that tracks the overall
// count of completed work items.
incrementProgress.Post(toolStripProgressBar3);
},
new ExecutionDataflowBlockOptions
{
CancellationToken = cancellationSource.Token,
MaxDegreeOfParallelism = 2
});
// Connect the two nodes of the pipeline. When the first node completes,
// set the second node also to the completed state.
startWork.LinkTo(
completeWork, new DataflowLinkOptions { PropagateCompletion = true });
// Create the dataflow action blocks that increment and decrement
// progress bars.
// These blocks use the task scheduler that is associated with
// the UI thread.
incrementProgress = new ActionBlock<ToolStripProgressBar>(
progressBar => progressBar.Value++,
new ExecutionDataflowBlockOptions
{
CancellationToken = cancellationSource.Token,
TaskScheduler = uiTaskScheduler
});
decrementProgress = new ActionBlock<ToolStripProgressBar>(
progressBar => progressBar.Value--,
new ExecutionDataflowBlockOptions
{
CancellationToken = cancellationSource.Token,
TaskScheduler = uiTaskScheduler
});
}
// Event handler for the Add Work Items button.
private void toolStripButton1_Click(object sender, EventArgs e)
{
// The Cancel button is disabled when the pipeline is not active.
// Therefore, create the pipeline and enable the Cancel button
// if the Cancel button is disabled.
if (!toolStripButton2.Enabled)
{
CreatePipeline();
// Enable the Cancel button.
toolStripButton2.Enabled = true;
}
// Post several work items to the head of the pipeline.
for (int i = 0; i < 5; i++)
{
toolStripProgressBar1.Value++;
startWork.Post(new WorkItem());
}
}
// Event handler for the Cancel button.
private async void toolStripButton2_Click(object sender, EventArgs e)
{
// 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,
incrementProgress.Completion,
decrementProgress.Completion);
}
catch (OperationCanceledException)
{
}
// Increment the progress bar that tracks the number of cancelled
// work items by the number of active work items.
toolStripProgressBar4.Value += toolStripProgressBar1.Value;
toolStripProgressBar4.Value += toolStripProgressBar2.Value;
// Reset the progress bars that track the number of active work items.
toolStripProgressBar1.Value = 0;
toolStripProgressBar2.Value = 0;
// Enable the Add Work Items button.
toolStripButton1.Enabled = true;
}
~Form1()
{
cancellationSource.Dispose();
}
}
}
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Threading.Tasks.Dataflow
Namespace CancellationWinForms
Partial Public Class Form1
Inherits Form
' A placeholder type that performs work.
Private Class WorkItem
' Performs 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, WorkItem)
' The second, and final, node in the dataflow pipeline.
Private completeWork As ActionBlock(Of WorkItem)
' Increments the value of the provided progress bar.
Private incrementProgress As ActionBlock(Of ToolStripProgressBar)
' Decrements the value of the provided progress bar.
Private decrementProgress As ActionBlock(Of ToolStripProgressBar)
' 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 synchronization
' 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.
startWork = New TransformBlock(Of WorkItem, WorkItem)(Function(workItem)
' Perform some 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 count of
' active work items in the next stage of the pipeline.
' Send the work item to the next stage of the pipeline.
workItem.DoWork(250)
decrementProgress.Post(toolStripProgressBar1)
incrementProgress.Post(toolStripProgressBar2)
Return workItem
End Function,
New ExecutionDataflowBlockOptions With {.CancellationToken = cancellationSource.Token})
' Create the second, and final, node in the pipeline.
completeWork = New ActionBlock(Of WorkItem)(Sub(workItem)
' Perform some 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.
workItem.DoWork(1000)
decrementProgress.Post(toolStripProgressBar2)
incrementProgress.Post(toolStripProgressBar3)
End Sub,
New ExecutionDataflowBlockOptions With {.CancellationToken = cancellationSource.Token,
.MaxDegreeOfParallelism = 2})
' Connect the two nodes of the pipeline. When the first node completes,
' set the second node also to the completed state.
startWork.LinkTo(
completeWork, New DataflowLinkOptions With {.PropagateCompletion = true})
' Create the dataflow action blocks that increment and decrement
' progress bars.
' These blocks use the task scheduler that is associated with
' the UI thread.
incrementProgress = New ActionBlock(Of ToolStripProgressBar)(
Sub(progressBar) progressBar.Value += 1,
New ExecutionDataflowBlockOptions With {.CancellationToken = cancellationSource.Token,
.TaskScheduler = uiTaskScheduler})
decrementProgress = New ActionBlock(Of ToolStripProgressBar)(
Sub(progressBar) progressBar.Value -= 1,
New ExecutionDataflowBlockOptions With {.CancellationToken = cancellationSource.Token,
.TaskScheduler = uiTaskScheduler})
End Sub
' Event handler for the Add Work Items button.
Private Sub toolStripButton1_Click(ByVal 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
' if 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 i As Integer = 0 To 4
toolStripProgressBar1.Value += 1
startWork.Post(New WorkItem())
Next i
End Sub
' Event handler for the Cancel button.
Private Async Sub toolStripButton2_Click(ByVal sender As Object, ByVal e 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, incrementProgress.Completion, decrementProgress.Completion)
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 += toolStripProgressBar1.Value
toolStripProgressBar4.Value += toolStripProgressBar2.Value
' Reset the progress bars that track the number of active work items.
toolStripProgressBar1.Value = 0
toolStripProgressBar2.Value = 0
' Enable the Add Work Items button.
toolStripButton1.Enabled = True
End Sub
Protected Overrides Sub Finalize()
cancellationSource.Dispose()
MyBase.Finalize()
End Sub
End Class
End Namespace
Az alábbi ábrán a futó alkalmazás látható.
