我正在尝试做类似光纤的代码,我可以进入任务并摆脱它。我试过的代码:
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
而导致死锁。 / p>
我的问题是,如何融合Task.Delay
和Task.Yield
,这样它不会消耗大量CPU,但仍能让其他任务工作?
答案 0 :(得分:6)
您可以Register
使用CancellationToken
来标记来源,而不是执行while循环:
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
进行有效的旋转等待,并在取消时直接标记完成的任务。