1.While(True)循环替代结构--while(!token.IsCancellationRequested)+await Task.Delay
using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TaskCancel
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Run_Click(object sender, RoutedEventArgs e)
{
StartPollAsync();
}
private void Stop_Click(object sender, RoutedEventArgs e)
{
if (_cts != null && !_cts.IsCancellationRequested)
{
_cts.Cancel();
}
}
private CancellationTokenSource _cts;
public async Task StartPollAsync()
{
// 防重复启动:如果正在运行直接返回
if (_cts != null && !_cts.IsCancellationRequested)
{
Console.WriteLine("轮询任务已经在运行中");
return;
}
// 如果旧cts存在先释放掉
_cts?.Dispose();
_cts = new CancellationTokenSource();
var token = _cts.Token;
// ⚠️去掉 await!不要等待后台循环完成,方法立刻返回
_ = Task.Run(async () =>
{
try
{
while (!token.IsCancellationRequested)
{
var data = ReadDevice();
if (data != null)
{
ProcessData(data);
}
Debug.Write(DateTime.Now.Millisecond.ToString());
await Task.Delay(5000, token);
}
}
catch (OperationCanceledException)//卡在可取消异步方法(Task.Delay (token))时 Cancel → 抛异常,进 catch
{
Debug.WriteLine("轮询循环:正常收到停止信号,已退出");//
}
catch (Exception ex)
{
Debug.WriteLine($"轮询循环发生异常:{ex.Message}");
}
finally//正在跑普通业务代码时 Cancel → while 条件失败,循环正常结束,不抛异常,跳过 catch 直接 finally
{
Debug.WriteLine("轮询任务已停止");
// 释放资源,并且清空引用
_cts?.Dispose();
_cts = null;
}
}, token);
await Task.CompletedTask;
}
private bool _isRunning;
public async Task StartPollAsync1()
{
if (_isRunning)
{
Console.WriteLine("轮询任务已经在运行中");
return;
}
_cts?.Dispose();
_cts = new CancellationTokenSource();
var token = _cts.Token;
_isRunning = true;
_ = Task.Run(async () =>
{
try
{
while (!token.IsCancellationRequested)
{
//轮询逻辑
await Task.Delay(2000, token);
}
}
catch (OperationCanceledException)
{
}
finally
{
_cts?.Dispose();
_cts = null;
_isRunning = false;
}
}, token);
await Task.CompletedTask;
}
public bool ReadDevice()
{
return false;
}
public void ProcessData(object data)
{
}
}
}