C# 异步取消
// .net8 Winform
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Async_Cancell
{
public partial class Form1 : Form
{
// [ 1: 使用变量控制进程 ]
// static bool Stop; // 新建一个布尔值,用于在循环的任务中作为标识。
// [ 2:使用 CancellationTokenSource ]
static CancellationTokenSource Stop;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = false;
}
private async void button1_Click(object sender, EventArgs e)
{
// 初始进度条初始值
progressBar1.Value = 0;
//======================================================
// [ 1: 使用变量控制进程 ] 。 注意:如果这里调用异步属性Result会报错。 适用简单脚本过程
// 说明: 如果任务中的标识为true 则跳出循环。 注意:但这并不会终止线程, 这只是跳出了线程的循环而已。
// Stop = false; // 停止标识
// textBox1.Text += tasks1().IsCompleted; // 因为该方法内部有控件操作,调用该方法会执行该方法。
// [ 2:使用 CancellationTokenSource ]
// 说明:该方法和以上似乎差不多, 也是跳出循环。 但是有个问题CancellationTokenSource的值无法恢复默认。 如果使用该类的Cancell方法改变了Token的值, 但却无法恢复为初始。
// Stop = new CancellationTokenSource();
// Task t2 = tasks2(); // 执行任务结果
// textBox1.Text += "任务是否正常执行:" + AnyDone.IsCompleted + "\r\n"; // 查看任务结果
// textBox1.Text += "返回任务结果:" + AnyDone.Result + "\r\n";
// 注意:如果直接使用方法返回,是无法正确获取任务结果的。 如: textBox1.Text += tasks2().Result.ToString() + "\r\n";
try
{
// 需要获取catch结果需要该方式执行 await tasks3(Stop.Token);
Task t3 = tasks3(Stop.Token);
textBox1.Text += "是否取消了任务:" + t3.IsCanceled + "\r\n";
}
catch (OperationCanceledException Ex)
{
textBox1.Text += Ex.Message + "\r\n";
}
// textbox 自动定位到底部, 注意该语句段需要放在方法的尾部. 因为要作为定位到最后的位置.
// textBox1.SelectionStart = textBox1.Text.Length; // 相当于 textBox1.Select(textBox1.Text.Length, 0);
textBox1.Select(textBox1.Text.Length, 0);
textBox1.ScrollToCaret();
}
/* // [ 1: 使用变量控制进程方法 ]
async Task tasks1()
{
for (int x = 0; x < 101; x++) { if (Stop) { break; } else { await Task.Delay(10); progressBar1.Value = x; } }
}
*/
/* // [ 2:使用 CancellationTokenSource 方法]
async Task<int> tasks2()
{
int num = 0;
for (int x = 0; x < 101; x++)
{
if (Stop.IsCancellationRequested)
{ label3.Text = Stop.IsCancellationRequested.ToString(); break; }
else
{ label3.Text = Stop.IsCancellationRequested.ToString(); await Task.Delay(10); progressBar1.Value = x; num = x; }
}
return num;
}
*/
async Task<int> tasks3(CancellationToken tokens)
{
int num = 0;
for (int x = 0; x < 101; x++)
{
if (tokens.IsCancellationRequested)
{
tokens.ThrowIfCancellationRequested(); // 触发错误
label3.Text = Stop.IsCancellationRequested.ToString();
}
else
{
label3.Text = Stop.IsCancellationRequested.ToString();
await Task.Delay(10); progressBar1.Value = x; num = x;
}
}
return num;
}
private void button2_Click(object sender, EventArgs e)
{
// [ 1: 使用变量控制进程方法 ]
// Stop = true; // 停止标识
// [ 2&3:使用 CancellationTokenSource ]
Stop.CancelAsync(); // 停止异步
label3.Text = "True";
}
private void button3_Click(object sender, EventArgs e)
{
Stop = new CancellationTokenSource(); // 新建CancellationTokenSource对象。 如果使用Cancell方法可以重新生成新对象初始值
button1.Enabled = true;
button2.Enabled = true;
label3.Text = "False";
}
}
}
## 执行过程
文章编写or整理的内容由作者完成,引用or参考会给出原文链接。