我正在尝试编写类似 fiber 的代码,这样我就可以进入任务并从中退出。我试过的代码:
class TaskActivity {
CancellationTokenSource _m=new CancellationTokenSource( int.MaxValue )
,_t=new CancellationTokenSource( int.MaxValue );
public async Task PauseTask( ) { //call and await it when I want to pause task inside itself
_m.Cancel( );
_t = new CancellationTokenSource( int.MaxValue );
while( !_t.IsCancellationRequested )
await Task.Yield( );
}
public async Task ResumeTask( ) { //call and wait for it when I want to resume a task from the main context
_t.Cancel( );
_m = new CancellationTokenSource( int.MaxValue );
while( !_m.IsCancellationRequested )
await Task.Yield( );
}
}
它运行良好,但是当我在 Task\Main 上下文中调用 Thread.Sleep
时它会消耗大量 CPU,因为它在循环中运行而不会在另一端停止。当我尝试 await Task.Delay( int.MaxValue, (_m\_t) );
而不是 await Task.Yield( );
时,它并没有消耗很多CPU 但它有时会死锁,因为 Task
不会屈服于另一个 Task
。
我的问题是,如何融合 Task.Delay
和 Task.Yield
使其不会消耗大量 CPU 但仍能让其他任务工作?
最佳答案
您可以 Register
而不是 while 循环使用 CancellationToken
在源被标记时通知您:
public Task PauseTask( )
{
_m.Cancel( );
_t = new CancellationTokenSource( int.MaxValue );
// Make a task yourself
var task = new TaskCompletionSource<bool>();
_t.Token.Register(() => task.TrySetResult(true)); // Mark the task done
return task.Task;
}
这避免了您通过 while
和 Task.Yield
使用的有效旋转等待,并在取消发生时直接将任务标记为已完成。
关于c# - Task.Delay 与 Task.Yield 融合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23875532/