Вызов отменыToken.Cancel() в Dispose of Controller?

У меня есть контроллер, где я создаю токен отмены в конструкторе и использую его в долго выполняющейся задаче ожидания(). Приводит ли удаление маркера отмены в Controller.Dispose() к отмене длительной задачи?

public class SomeController : BaseInternalController
{
    private CancellationTokenSource cancellationTokenSource;

    public MyController()
    {
        cancellationTokenSource = new CancellationTokenSource();
    }

    public async Task<HttpResponseMessage> Post(SomeData data)
    {
        foreach (var item in data)
        {
            await longRunningTask(item, cancellationTokenSource.token);
        }

    }

    protected override void Dispose(bool disposing)
    {
        if (cancellationTokenSource != null)
        {
            cancellationTokenSource.Cancel();
            cancellationTokenSource.Dispose();
            cancellationTokenSource = null;
        }
        base.Dispose(disposing);
    }
}

person user3318597    schedule 20.05.2017    source источник
comment
Контроллер не будет удален до тех пор, пока задача, возвращаемая Post, не завершится, то есть после завершения longRunningTask.   -  person Stephen Cleary    schedule 20.05.2017
comment
Вы можете добавить CancellationToken в свой метод Post. Это будет заполнено фреймворком и установлено в отмененное состояние, если клиент отключится. Таким образом, клиент может решить, когда он больше не хочет ждать.   -  person ckuri    schedule 20.05.2017
comment
Спасибо @StephenCleary   -  person user3318597    schedule 24.05.2017


Ответы (1)


Приводит ли удаление маркера отмены в Controller.Dispose() к отмене длительной задачи?

Зависит от того, как был реализован ваш longRunningTask. В этом методе вы должны явно проверить, запрашивается ли отмена:

token.ThrowIfCancellationRequested();

После вызова этого метода ваша задача будет отменена.

Пример отмены

Если в следующем примере ThrowIfCancellationRequested не будет вызываться, задача будет выполняться вечно:

var cts = new CancellationTokenSource();
Task.Run(() =>
{
    while (true)
        cts.Token.ThrowIfCancellationRequested();
}, cts.Token);

Вы можете узнать больше об отмене здесь .


Обратите внимание, что после установки cancellationTokenSource на null вы можете получить NullReferenceException в цикле foreach. Я бы предложил скопировать ваш токен в локальную переменную:

public async Task<HttpResponseMessage> Post(SomeData data)
{
    var token = cancellationTokenSource.Token;
    foreach (var item in data)
    {
        await longRunningTask(item, token);
    }
}
person Vitali    schedule 20.05.2017