简体   繁体   中英

Is there a way to force a context switch without Task.Delay in async code

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM