接下來看比較複雜的範例。
取消多個任務
多個任務在不同時間開始執行,但需要在同一個時間結束。以下是畫面。
需求
當我們按上面的 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 的訊號
}
}
}
範例下載
沒有留言:
張貼留言