C#中多線程使用CancellationTokenSource進行線程管理
更新時間:2025年09月30日 08:22:02 作者:鈴兒~響叮當(dāng)
本文主要介紹了C#中多線程使用CancellationTokenSource進行線程管理,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
1. Xml 代碼
<Grid Margin="15" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="120" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<!-- 添加任務(wù) -->
<Label Content="Task Number" Style="{StaticResource LabelStyle}" />
<TextBox
x:Name="xTxtTaskNum"
Grid.Column="1"
Style="{StaticResource TextBoxStyle}" />
<Button
Grid.Column="3"
Click="BtnClick_CreateTasks"
Content="創(chuàng)建任務(wù)"
Style="{StaticResource BtnStyle}" />
<!-- 開始任務(wù) -->
<Label
Grid.Row="1"
Content="Task Index"
Style="{StaticResource LabelStyle}" />
<TextBox
x:Name="xTxtStartIdx"
Grid.Row="1"
Grid.Column="1"
Style="{StaticResource TextBoxStyle}" />
<Button
Grid.Row="1"
Grid.Column="3"
Click="BtnClick_StartTask"
Content="開始該任務(wù)"
Style="{StaticResource BtnStyle}" />
<!-- 結(jié)束任務(wù) -->
<Label
Grid.Row="2"
Content="Task Index"
Style="{StaticResource LabelStyle}" />
<TextBox
x:Name="xTxtStopIdx"
Grid.Row="2"
Grid.Column="1"
Style="{StaticResource TextBoxStyle}" />
<Button
Grid.Row="2"
Grid.Column="3"
Click="BtnClick_StopTask"
Content="停止該任務(wù)"
Style="{StaticResource BtnStyle}" />
<!-- 暫停任務(wù) -->
<Label
Grid.Row="3"
Content="Task Index"
Style="{StaticResource LabelStyle}" />
<TextBox
x:Name="xTxtPauseIdx"
Grid.Row="3"
Grid.Column="1"
Style="{StaticResource TextBoxStyle}" />
<Button
Grid.Row="3"
Grid.Column="3"
Click="BtnClick_PauseTask"
Content="暫停該任務(wù)"
Style="{StaticResource BtnStyle}" />
<!-- 恢復(fù)任務(wù) -->
<Label
Grid.Row="4"
Content="Task Index"
Style="{StaticResource LabelStyle}" />
<TextBox
x:Name="xTxtResumeIdx"
Grid.Row="4"
Grid.Column="1"
Style="{StaticResource TextBoxStyle}" />
<Button
Grid.Row="4"
Grid.Column="3"
Click="BtnClick_ResumTask"
Content="恢復(fù)該任務(wù)"
Style="{StaticResource BtnStyle}" />
</Grid>2. 代碼實現(xiàn)
public partial class TestCancellationTokenThreads : Window
{
private ConcurrentDictionary<int, TaskInfo> _dictTaskInfo = new();
private int _taskNum = 0;
public TestCancellationTokenThreads()
{
InitializeComponent();
}
private void BtnClick_CreateTasks(object sender, RoutedEventArgs e)
{
_taskNum = Convert.ToInt32(xTxtTaskNum.Text);
for (int i = 0; i < _taskNum; i++)
{
TaskInfo taskInfo = new()
{
Name = $"Task{i + 1}",
Task = null,
Cts = null,
IsPause = false,
};
_dictTaskInfo.TryAdd(i, taskInfo);
}
Debug.WriteLine($"{_taskNum}個任務(wù)創(chuàng)建成功!");
}
private void BtnClick_StartTask(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(xTxtStartIdx.Text)) return;
int idx = Convert.ToInt32(xTxtStartIdx.Text);
if (idx < 0 || idx >= _taskNum)
{
Debug.WriteLine($"任務(wù)序號超出任務(wù)總數(shù){_taskNum}");
return;
}
TaskInfo taskInfo = _dictTaskInfo[idx];
if ((taskInfo.Cts != null && !taskInfo.Cts.IsCancellationRequested) || (taskInfo.Task != null && !taskInfo.Task.IsCompleted))
{
Debug.WriteLine($"任務(wù): {taskInfo.Name}正在運行...");
return;
}
taskInfo.Cts = new();
taskInfo.IsPause = false; //啟動任務(wù)后,自動開始
Debug.WriteLine("任務(wù)開始運行...");
CancellationToken token = taskInfo.Cts.Token;
//創(chuàng)建任務(wù)
taskInfo.Task = Task.Run(async () =>
{
int numIdx = 0;
//執(zhí)行任務(wù)的,用 Token 的 IsCancellationRequested
while (!token.IsCancellationRequested)
{
if (!taskInfo.IsPause)
{
Debug.WriteLine(numIdx);
numIdx++;
}
try
{
await Task.Delay(1000, token);
}
catch (OperationCanceledException)
{
break; //取消則立刻退出
}
}
}, token);
}
private async void BtnClick_StopTask(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(xTxtStopIdx.Text)) return;
int idx = Convert.ToInt32(xTxtStopIdx.Text);
if (idx < 0 || idx >= _taskNum)
{
Debug.WriteLine($"任務(wù)序號超出任務(wù)總數(shù){_taskNum}");
return;
}
TaskInfo taskInfo = _dictTaskInfo[idx];
if (taskInfo.Cts == null || taskInfo.Task == null) return;
//觸發(fā)取消的操作,用 Cts 的 IsCancellationRequested
if (!taskInfo.Cts.IsCancellationRequested)
{
taskInfo.Cts.Cancel();
}
try
{
await taskInfo.Task.WaitAsync(TimeSpan.FromMilliseconds(3000));
}
catch (TimeoutException)
{
Debug.WriteLine($"任務(wù):{taskInfo.Name} 停止超時!");
}
finally
{
taskInfo.Cts.Dispose();
taskInfo.Cts = null;
taskInfo.Task = null;
}
Debug.WriteLine($"任務(wù):{taskInfo.Name} 已停止");
}
private void BtnClick_PauseTask(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(xTxtPauseIdx.Text)) return;
int idx = Convert.ToInt32(xTxtPauseIdx.Text);
if (idx < 0 || idx >= _taskNum)
{
Debug.WriteLine($"任務(wù)序號超出任務(wù)總數(shù){_taskNum}");
return;
}
TaskInfo taskInfo = _dictTaskInfo[idx];
taskInfo.IsPause = true;
}
private void BtnClick_ResumTask(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(xTxtResumeIdx.Text)) return;
int idx = Convert.ToInt32(xTxtResumeIdx.Text);
if (idx < 0 || idx >= _taskNum)
{
Debug.WriteLine($"任務(wù)序號超出任務(wù)總數(shù){_taskNum}");
return;
}
TaskInfo taskInfo = _dictTaskInfo[idx];
taskInfo.IsPause = false;
}
}
public class TaskInfo
{
public string? Name { get; set; }
public Task? Task { get; set; }
public CancellationTokenSource? Cts { get; set; }
public bool IsPause { get => _isPause; set => _isPause = value; }
public object Locker { get; set; } = new();
//以這樣的方式,保留 volatile 的功能性
//volatile: 適用于一個線程讀,一個線程寫的情況,并且是簡單類型的簡單操作 (不能用于 struct等、IsPause = !IsPause 這種 "修改+寫入"),并且只能字段
private volatile bool _isPause;
}3. 運行

到此這篇關(guān)于C#中多線程使用CancellationTokenSource進行線程管理的文章就介紹到這了,更多相關(guān)C# 線程管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c#使用linq技術(shù)創(chuàng)建xml文件的小例子
c#使用linq技術(shù)創(chuàng)建xml文件的小例子,需要的朋友可以參考一下2013-03-03
C#實現(xiàn)控制線程池最大數(shù)并發(fā)線程
這篇文章主要介紹了C#實現(xiàn)控制線程池最大數(shù)并發(fā)線程的相關(guān)資料,需要的朋友可以參考下2016-07-07
C#編程實現(xiàn)連接SQL SERVER數(shù)據(jù)庫實例詳解
這篇文章主要介紹了C#編程實現(xiàn)連接SQL SERVER數(shù)據(jù)庫的方法,以實例形式較為詳細的分析了C#連接SQL SERVER數(shù)據(jù)庫的相關(guān)步驟與具體實現(xiàn)技巧,需要的朋友可以參考下2015-11-11

