5

常にブロックされるタスクがあり、タスクをキャンセルするために使用される CancellationToken が渡されます。ただし、タスクのキャンセル時に実行するように設定されている継続タスクは実行されません。コードは次のとおりです。

    _tokenSrc = new CancellationTokenSource();
    var cnlToken = _tokenSrc.Token;

    Task.Run(() => 
          // _stream.StartStream() blocks forever  
          _stream.StartStream(), cnlToken)
        .ContinueWith(ant =>
        {
            _logger.Warn("Stream task cancellation requested, stopping the stream");
            _stream.StopStream();
            _stream = null;
            _logger.Warn("Stream stopped and task cancelled");
        }, TaskContinuationOptions.OnlyOnCanceled);

後でコードのどこかで...

_tokenSrc.Cancel();

_stream.StartStream() に Task を使用しなければならなかった理由は、この呼び出しが永久にブロックされるためです (私が制御できない API、_stream は Web サービスからデータをストリーミングするサードパーティの Api を参照することに注意してください)。それは別のスレッドで。

タスクをキャンセルする最良の方法は何ですか?

4

3 に答える 3

2

Registerメソッド onを使用してCancellationToken、キャンセルが要求されたときに呼び出されるデリゲートを登録できます。デリゲートでは、ブロックされた操作のブロックを解除するメソッドを呼び出します。

何かのようなもの:

_tokenSrc = new CancellationTokenSource();
var cnlToken = _tokenSrc.Token;

var task = Task.Factory.StartNew(() =>
{
    using(var tokenReg = cnlToken.Register(() => 
        {
            _logger.Warn("Stream task cancellation requested, stopping the stream");
            _stream.StopStream();
            _stream = null;
            _logger.Warn("Stream stopped and task cancelled");
        }))
    {
        _stream.StartStream(), cnlToken)
    }
}, cnlToken);

MSDN 「方法: キャンセル要求のコールバックを登録する」

于 2015-07-08T07:59:06.120 に答える
2

[アップデート]

問題を修正したコードを以下に変更しました。

Task.Run(() =>
{
    var innerTask = Task.Run(() => _stream.StartStream(), cToken);
    innerTask.Wait(cToken);
}, cToken)
.ContinueWith(ant =>
{
    _logger.Warn("Stream task cancellation requested, stopping the stream");
    _stream.StopStream();
    _stream = null;
    _logger.Warn("Stream stopped and task cancelled");
}, TaskContinuationOptions.OnlyOnCanceled);
于 2014-03-29T20:40:28.730 に答える