接下來看比較複雜的範例。
取消多個任務
多個任務在不同時間開始執行,但需要在同一個時間結束。以下是畫面。
需求
當我們按上面的 Start 鍵,就開始第一個計數器。當按下面的 Start 鍵,就開始第二個計數器。而按 Stop All 鍵時,兩個計數器同時停止。
在 Task 的初始時,指定同一個 CancelTokenSource 的 CancelToken,就可以使用同一個CancelTokenSource 來 Cancel 多個 Task
CancelMutilpleTasks.xaml
<Window x:Class="TPL_CancelAnApp.CancelMutilpleTasks" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <StackPanel > <StackPanel> <TextBlock x:Name="txtTotal1" /> <Button x:Name="btnStart1" Click="btnStart_Click">Start</Button> </StackPanel> <StackPanel> <TextBlock x:Name="txtTotal2" /> <Button x:Name="btnStart2" Click="btnStart_Click">Start</Button> </StackPanel> <Button x:Name="btnStop" Click="btnStop_Click">Stop All</Button> <TextBlock Name="txtStatus" /> </StackPanel> </Grid> </Window>
CancelMutilpleTasks.xaml.cs
using System; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; using System.Windows.Controls; namespace TPL_CancelAnApp { public partial class CancelMutilpleTasks : Window { CancellationTokenSource tokenSource = new CancellationTokenSource(); Task[] tasks = new Task[2]; public CancelMutilpleTasks() { InitializeComponent(); InitialTask(); } private void InitialTask() { CancellationToken token = tokenSource.Token; //建立第一個 task tasks[0] = new Task(() => { long total = 0; while (total < 1000) { total++; Thread.Sleep(2); Action<string> action = new Action<string>(s => txtTotal1.Text = s); txtTotal1.Dispatcher.BeginInvoke(action, DispatcherPriority.Normal, total.ToString()); token.ThrowIfCancellationRequested(); }; }, token); //建立第二個 task tasks[1] = new Task(() => { long total = 0; while (total < 1000) { total++; Thread.Sleep(2); Action<string> action = new Action<string>(s => txtTotal2.Text = s); txtTotal2.Dispatcher.BeginInvoke(action, DispatcherPriority.Normal, total.ToString()); token.ThrowIfCancellationRequested(); }; }, token); Task.Factory.StartNew(() => { token.WaitHandle.WaitOne(); txtStatus.Dispatcher.BeginInvoke(new Action(() => txtStatus.Text = "使用者要求停止。")); }); } private void btnStart_Click(object sender, RoutedEventArgs e) { txtStatus.Text = "進行中"; Button button = sender as Button; int index = int.Parse(button.Name.Substring(button.Name.Length - 1)); tasks[index-1].Start(); //啟動指定的任務 } private void btnStop_Click(object sender, RoutedEventArgs e) { btnStart2.IsEnabled = btnStart1.IsEnabled = false; tokenSource.Cancel(); //發出 Cencel 的訊號 } } } 範例下載
沒有留言:
張貼留言