C# 从外部取消任务的执行

    根据微软官方文档,推荐用TAP模式编写异步程序,提供了用于取消Task的 CancellationToken 标记,实际应用中可以new 一个CancellationTokenSource对象。当我们需要一个循环执行的机制时(在Thread方式下通常是用Thread.Sleep,在Task下就是await Task.Delay),需要停下来时,由于线程或Task从外部都是无法停止的,要在内部通过这个 CancellationToken 来自行停下来, 那么就有两个选择:

  1.  每次循环开始时,使用 cancellationToken.IsCancellationRequested 判断要不要停下来;
  2. 在Task.Delay里面加上cancellationToken参数,然后截获Task.Delay抛出的 OperationCanceledException 异常。

  以Delay 50ms为例,测试结果表明,Cancel前等待时间 方法1要短于方法2,估计方法2的 throw-try-catch 代价比较高,推荐使用方法1

    方法1,只通过 IsCancellationRequested 测试:

static void Main(string[] args)
{
	System.Threading.CancellationTokenSource quitFlag = new System.Threading.CancellationTokenSource();
	testCancel1(quitFlag.Token);
	Task.Delay(250).Wait();
	Console.WriteLine(DateTime.Now.ToString("HH:mm:ss fff") + " Cancel...");
	quitFlag.Cancel();
	Console.Read();
}

static async void testCancel1(System.Threading.CancellationToken cancellationToken)
{
	while (!cancellationToken.IsCancellationRequested)
	{
		Console.WriteLine(DateTime.Now.ToString("HH:mm:ss fff"));
		await Task.Delay(50);
	}
	Console.WriteLine(DateTime.Now.ToString("HH:mm:ss fff") + " Cancelled");
}
//09:50:18 286
//09:50:18 413
//09:50:18 474
//09:50:18 527
//09:50:18 587
//09:50:18 603 Cancel...
//09:50:18 649 Cancelled

     方法2,通过 IsCancellationRequested 和 Delay(50,cancellationToken) 截获异常:

static void Main(string[] args)
{
	System.Threading.CancellationTokenSource quitFlag = new System.Threading.CancellationTokenSource();
	testCancel1(quitFlag.Token);
	Task.Delay(250).Wait();
	Console.WriteLine(DateTime.Now.ToString("HH:mm:ss fff") + " Cancel...");
	quitFlag.Cancel();
	Console.Read();
}

static async void testCancel2(System.Threading.CancellationToken cancellationToken)
{
	try
	{
		while (!cancellationToken.IsCancellationRequested)
		{
			Console.WriteLine(DateTime.Now.ToString("HH:mm:ss fff"));
			await Task.Delay(50, cancellationToken);
		}
		Console.WriteLine(DateTime.Now.ToString("HH:mm:ss fff") + " Cancelled");
	}
	catch(OperationCanceledException ex)
	{
		Console.WriteLine(DateTime.Now.ToString("HH:mm:ss fff") + " Throwed");
	}
}
//09:53:50 718
//09:53:50 843
//09:53:50 900
//09:53:50 964
//09:53:51 029
//09:53:51 031 Cancel...
//09:53:51 808 Throwed

       

猜你喜欢

转载自blog.csdn.net/xhydongda/article/details/108593292