A.
CancellationToken
通常在通过mongodb驱动程序编写异步I/O代码时使用(
InsertOneAsync
例如)。让我们考虑以下场景。你在做早餐。
Example taken from here.
static async Task Main(string[] args)
{
//Find eggs and bacon in database
Task<List<Egg>> eggTask = FindEggsAsync(2);
Task<List<Bacon>> baconTask = FindBaconAsync(3);
Coffee cup = PourCoffee();
Console.WriteLine("coffee is ready");
Juice oj = PourOJ();
Console.WriteLine("oj is ready");
List<Egg> eggs = await eggTask;
List<Bacon> bacon = await baconTask;
FryEggs(eggs);
Console.WriteLine("eggs are ready");
FryBacon(bacon);
Console.WriteLine("bacon is ready");
Console.WriteLine("Breakfast is ready!");
}
这是很好的异步代码,对吗?只有当我们需要任务的结果时,我们才在等待任务。
我们首先需要通过I/O找到我们的鸡蛋和培根,让我们想象一下,我们的鸡蛋和培根存储在mongodb中,而不是食品储藏室。所以我们给你的两个想象中的孩子
tasks
从食品储藏室(数据库)中查找鸡蛋和培根。
当他们发现你给自己倒了一杯OJ和咖啡时,你已经准备好了(基本上是任何CPU工作)。
有了咖啡和果汁,你意识到你已经准备好了配料,所以你
await
返回给孩子的任务和
FryEggs
和
FryBacon
。
早餐做得很好——但让我们假设你是一个脾气暴躁的人,度过了一个糟糕的早晨,你的咖啡洒了,这让你完全不吃早餐(我知道这很荒谬),你需要告诉你的孩子不要再找了。让我们修改上面的代码来集成这一点。
static async Task Main(string[] args)
{
var cancellationToken = new CancellationTokenSource();
//Find eggs and bacon in database
Task<List<Egg>> eggTask = FindEggsAsync(2,cancellationToken.Token);
Task<List<Bacon>> baconTask = FindBaconAsync(3,cancellationToken.Token);
Coffee cup = PourCoffee();
if(cup.IsSpilled())
{
//Freak out and cancel tasks
cancellationToken.Cancel();
//Quit
Environment.Exit(0)
}
Console.WriteLine("coffee is ready");
Juice oj = PourOJ();
Console.WriteLine("oj is ready");
List<Egg> eggs = await eggTask;
List<Bacon> bacon = await baconTask;
FryEggs(eggs);
Console.WriteLine("eggs are ready");
FryBacon(bacon);
Console.WriteLine("bacon is ready");
Console.WriteLine("Breakfast is ready!");
//Dispose of token
cancellationToken.Dispose();
}
取消令牌本身将传递给相关mongodb驱动程序方法的异步版本。
FindAsync
将在我们的两个find方法中调用,并传入取消令牌。如果任务尚未完成,它将相应地取消输入/输出操作。