Task.Delay сливается с Task.Yield?

1

Я пытаюсь сделать волоконно-подобный код, который я могу получить в задаче и выйти из него. Код, который я пробовал:

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( );
    }
}

Он работает хорошо, но он потребляет много CPU, когда я вызываю Thread.Sleep в контексте Task\Main, потому что он работает в цикле без остановки на другой стороне. Когда я попытался await Task.Delay( int.MaxValue, (_m\_t) ); вместо await Task.Yield( ); , он не потреблял много CPU, но вместо этого он затормозил иногда, потому что Task не уступает другой Task.

Мой вопрос заключается в том, как сплавить Task.Delay и Task.Yield чтобы он не потреблял много процессора, но все же позволял другим задачам работать?

Теги:
task

1 ответ

6

Вместо выполнения цикла while вы можете Register в 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 и непосредственно исполняется задача завершается, когда происходит отмена.

  • 0
    Мне очень жаль, что я начинающий. Когда я переключил переменные и поместил код в ResumeTask он зашёл в тупик. Он переключился на Task , переключился обратно в основной контекст, снова на Task и умер. Кстати в основном контексте я использовал activity.ResumeTask( ).Wait( ); , все нормально?
  • 0
    @KugBuBu Вы должны использовать await , а не вызывать Wait для задач ...
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню