I have code with looks something like:
I was trying to avoid putting it in a Task.Run because it is async and should run fine on the main thread
However it does not do a context switch (and will run forever), unless I insert a Task.Delay into the loop
Is there a better way of achieving this (Without 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
}
}
I'm trying to unit test cancellation when I have a heavy workload an encountered this problem.
Try
async Task DoSomething(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
//await Task.CompletedTask; //you can omit this line
await Task.Yield();
}
}
If you want to simulate a cancelable operation, the simplest way is probably this:
Task DoSomething(CancellationToken cancellationToken)
{
return Task.Delay(Timeout.Infinite, cancellationToken);
}
The cancellationToken
parameter has canceling semantics , meaning that when the token is canceled, the Task
will transition to the Canceled
state. If you want it to have stopping semantics, which is the non standard semantics for a CancellationToken
, you could do this:
async Task DoSomething(CancellationToken stoppingToken)
{
try { await Task.Delay(Timeout.Infinite, stoppingToken); }
catch (OperationCanceledException) { }
}
Now when the token is canceled, the Task
will transition to the RanToCompletion
state. Be aware that it's extremely rare to see a CancellationToken
parameter with stopping semantics in the standard .NET libraries.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.