Лучшие практики для прерывания потоковой передачи asyn c - PullRequest
0 голосов
/ 21 апреля 2020

Я работаю над действием основного контроллера asp. net, которое предоставляет поток в течение X секунд или до отмены в зависимости от того, что произойдет первым.

Мой первый подход заключался в асинхронном копировании потока в ответ, таким образом, я довольно легко могу использовать токен отмены, передав его в CopyToAsyn c.

[HttpGet]
[Route("getstream1")]
public async Task GetStream1(CancellationToken cancellationToken)
{
    var stream = await new HttpClient().GetStreamAsync("http://localhost:4747/video");

    var cst = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
    var ct = cst.Token;

    Response.OnStarting(() =>
    {
        cst.CancelAfter(5000);
        return Task.CompletedTask;
    });

    Response.StatusCode = 200;
    Response.ContentType = "video/stream";
    await Response.StartAsync(ct);

    try
    {
        await stream.CopyToAsync(Response.Body, 1024, ct);
    }
    catch (Exception ex)
    {
        if (ex is TaskCanceledException || ex is OperationCanceledException)
        {
            return;
        }

        throw;
    }
}

Моя вторая идея состояла в том, чтобы вернуть его как ответ файлового потока и запустить и забыть задачу, которая ожидает заданное количество времени и прерывает HttpContext или отменяется пользователем с помощью токена отмены.

[HttpGet]
[Route("getstream2")]
public async Task<IActionResult> GetStream2(CancellationToken cancellationToken)
{
    var stream = await new HttpClient().GetStreamAsync("http://localhost:4747/video");

    Task.Factory.StartNew(async () =>
    {
        await Task.Delay(5000, cancellationToken);

        try
        {
            HttpContext.Abort();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);                        
        }
    }, cancellationToken).ContinueWith(task =>
        {
            // handle exception
        }
    );

    return new FileStreamResult(stream, "video/stream");
}

Мой вопрос. Один из этих подходов лучше, чем другой? Есть ли лучший способ реализовать это? Можно ли позвонить Abort на HttpContext, когда я хочу закончить свой ответ?

...