我的代码看起来像:
我试图避免把它放在一个任务。运行,因为它是异步的,应该在主线程上运行良好
然而,它不做上下文切换(并将永远运行),除非我插入一个任务。延迟进入循环
有没有更好的方法来实现这个(没有Task.Run)?
var tasks = new List<Task>();
var cts = new CancellationTokenSource();
tasks.Add(DoSomething(cts.Token));
cts.Cancel();
Task.WaitAll(tasks.ToArray());
Console.WriteLine("Done");
async Task DoSomething(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.CompletedTask;
await Task.Delay(1); // Without this is doesn't do context switch
}
}
我在尝试取消单元测试时,工作负载很重,遇到了这个问题。
Try
async Task DoSomething(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
//await Task.CompletedTask; //you can omit this line
await Task.Yield();
}
}
如果您想模拟一个可取消的操作,最简单的方法可能是:
Task DoSomething(CancellationToken cancellationToken)
{
return Task.Delay(Timeout.Infinite, cancellationToken);
}
cancellationToken
参数具有取消语义,即当令牌被取消时,Task
将转移到Canceled
状态。如果您希望它具有停止语义,这是CancellationToken
的非标准语义,您可以这样做:
async Task DoSomething(CancellationToken stoppingToken)
{
try { await Task.Delay(Timeout.Infinite, stoppingToken); }
catch (OperationCanceledException) { }
}
现在,当令牌被取消时,Task
将过渡到RanToCompletion
状态。请注意,在标准。net库中很少看到带有停止语义的CancellationToken
参数。