c# - Task.Delay 与 Task.Yield 融合?

标签 c# task

我正在尝试编写类似 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.DelayTask.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;
}

这避免了您通过 whileTask.Yield 使用的有效旋转等待,并在取消发生时直接将任务标记为已完成。

关于c# - Task.Delay 与 Task.Yield 融合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23875532/

相关文章:

c# - 在 ASP.NET Web API2 webservice 中实现 OAuth 访问 token

c# - 使用 Roslyn 更改文件

c# - 取字符串的最后n行c#

C# 将字符串元素数组传递给 Task.Run

c# - 任务与线程差异

gradle - Gradle任务取决于已执行的任务

c# - 在 SVN 存储库中存储 Visual C# 项目的约定

c# - 视觉风格独立绘图

java - 在Spring中实例化一个新线程来定期执行任务

json - 你能通过一次查询获取 Rally API 要求、缺陷和所有任务吗