在.NET环境中,经常需要执行一些异步任务,这些任务可能是无限循环的,也可能是有限循环的。在某些情况下,需要能够优雅地中断这些任务。为了实现这一功能,可以利用CancellationTokenSource
和CancellationToken
。
首先,CancellationTokenSource
提供了一种方式来通知其CancellationToken
已被取消。当一个操作需要被取消时,CancellationToken
会发出通知。
接下来,将通过一个简单的例子来演示如何创建一个新的Task
,并使用Task.Factory.StartNew
方法来启动它。在这个过程中,将传递一个取消令牌给任务,以及传递给主循环。
此外,还将使用TaskCreationOption.LongRunningTask
参数和TaskScheduler.Default
。TaskCreationOption.LongRunningTask
指示任务是一个长时间运行的、粗粒度的操作,它涉及的组件数量较少,但每个组件的规模较大。这为TaskScheduler
提供了一个提示,表明可能需要超额订阅。超额订阅允许创建的线程数量超过硬件线程的可用数量。
以下是实现这一功能的简单示例代码。可以在LinqPad
上运行这段代码,或者创建一个新的控制台项目。请记住包含System.Threading.Tasks
命名空间。
void Main()
{
CancellationTokenSource cts = new CancellationTokenSource();
var token = cts.Token;
Task t = Task.Factory.StartNew(
() =>
{
MainLoop(token);
},
token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default
);
Console.ReadLine();
cts.Cancel();
try
{
t.Wait();
}
catch (AggregateException ae)
{
// 捕获内部异常
}
catch (Exception crap)
{
// 捕获其他异常
}
}
void MainLoop(CancellationToken token)
{
while (true)
{
// 在这里执行某些操作
Console.Write(".");
Thread.Sleep(100);
// 如果需要,在抛出取消请求之前进行其他清理
if (token.IsCancellationRequested)
{
// 清理
"cleanup".Dump();
token.ThrowIfCancellationRequested();
}
}
}
创建任务后,它将自动开始执行。在这种情况下,不需要等待任何返回变量,但必须这样做,以便在发生AggregatedException
时能够恢复。