亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C#中多線程使用CancellationTokenSource進(jìn)行線程管理

 更新時(shí)間:2025年09月30日 08:22:02   作者:鈴兒~響叮當(dāng)  
本文主要介紹了C#中多線程使用CancellationTokenSource進(jìn)行線程管理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(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}" />

    <!--  開(kāi)始任務(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="開(kāi)始該任務(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. 代碼實(shí)現(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}個(gè)任務(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ù)序號(hào)超出任務(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}正在運(yùn)行...");
            return;
        }
        taskInfo.Cts = new();
        taskInfo.IsPause = false;   //啟動(dòng)任務(wù)后,自動(dòng)開(kāi)始
        Debug.WriteLine("任務(wù)開(kāi)始運(yùn)行...");

        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ù)序號(hào)超出任務(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} 停止超時(shí)!");
        }
        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ù)序號(hào)超出任務(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ù)序號(hào)超出任務(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: 適用于一個(gè)線程讀,一個(gè)線程寫(xiě)的情況,并且是簡(jiǎn)單類型的簡(jiǎn)單操作 (不能用于 struct等、IsPause = !IsPause 這種 "修改+寫(xiě)入"),并且只能字段
    private volatile bool _isPause; 
}

3. 運(yùn)行

到此這篇關(guān)于C#中多線程使用CancellationTokenSource進(jìn)行線程管理的文章就介紹到這了,更多相關(guān)C# 線程管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論