CancellationToken на страницах Blazor?

Прожив под камнем в течение 2 лет, я столкнулся с Blazor на моем новом рабочем месте, и мне нужно много наверстать после того, как я в основном выполнял MVC ASP.NET Framework до 2 лет.

Пробуя себя на стороне сервера Blazor, я попытался применить свои прошлые знания, которые включали токены отмены для асинхронных операций, и я не смог найти много информации о них в сочетании с Blazor.

Они все еще являются передовой практикой или в какой-то момент устарели? Я нашел этот ранее заданный вопрос, в котором рекомендуется создать источник токенов для OnInitializedAsync() метода и отменить его Dispose(), что я, честно говоря, считаю немного грубым. (Мне нужно было бы реализовать это для каждой страницы, и вы знаете ... СУХОЙ)

Я также нашел эту статью о расширенных сценариях в Microsoft Docs, в котором объясняется, как реализовать обработчик цепей, который, честно говоря, немного выходит за рамки меня прямо сейчас и, скорее всего, выходит за рамки моего небольшого домашнего проекта.

Для сравнения, в asp.net Framework MVC я бы создал такой контроллер:

namespace SampleWebsite.Controllers
{
    public class SampleController : ApiController
    {
        private readonly MyEntities _entities = new MyEntities();

        public async Task<IHttpActionResult> MyAsyncApi(CancellationToken cancellationToken)
        {
            var result = _entities.MyModel.FirstOrDefault(e => e.Id == 1, cancellationToken: cancellationToken);
            return OK(result);
        }
    }
}

CancellationToken будет внедрен asp.net Framework / Core и напрямую связан с текущим каналом подключения контекста. Следовательно, если пользователь закрывает соединение, токен становится недействительным.

Я бы предположил, что для asp.net core и blazor, где инъекции зависимостей составляют большую часть, это будет иметь место и здесь, но я не смог найти здесь никакой документации по этому поводу.

Итак, следует ли на этом этапе по-прежнему использовать токены отмены или Microsoft творит чудеса в фоновом режиме для асинхронных задач? И если да, то какая реализация будет лучшей?

РЕДАКТИРОВАТЬ: Вот мои настройки, чтобы уточнить:

Компонент Blazor:

@page "/Index"
@inject IIndexService Service

@* Some fancy UI stuff *@

@code {
    private IEnumerable<FancyUiValue> _uiValues;

    protected override async Task OnInitializedAsync()
    {
        _uiValues = await Service.FetchCostlyValues();
    }
}

И внедренный сервис-класс, который делает тяжелую работу:

public interface IIndexService
{
    Task<IEnumerable<FancyUiValue>> FetchCostlyValues();
}

public class IndexService : IIndexService
{
    public async Task<IEnumerable<FancyUiValue>> FetchCostlyValues()
    {
        var uiValues = await heavyTask.ToListAsync(); // <-- Best way to get a cancellationtoken here?
        return uiValues;
    }
}

Мой вопрос: как лучше всего получить токен в определенной части кода или это не имеет значения, потому что сервер убьет все запущенные задачи, когда соединение (например) завершится?


person Kyte    schedule 21.06.2020    source источник
comment
Ваше редактирование помогает, но у вас все еще нет обработки исключений. Что вы хотите делать при ошибке? Или на тайм-аут?   -  person Henk Holterman    schedule 21.06.2020
comment
@HenkHolterman: Вопрос касался лучших практик для отмены асинхронных задач в Blazor, а не обработки исключений. Я не слишком хорошо знаком с двусторонней двоичной связью Blazor, мой изучаемый процесс вращается вокруг того, что, если пользователь запускает дорогостоящую асинхронную задачу (скажем: создание отчета в формате PDF), а затем переходит на другую страницу ?. Из моих знаний MVC задача async будет продолжать работать и потреблять ресурсы, а затем возвращается и либо игнорируется контроллером в родительском потоке, либо отправляется и отклоняется клиентом.   -  person Kyte    schedule 22.06.2020
comment
Да, для такой работы (PDF) я бы использовал CancelSrc. И Dispose (). Но обычно вы должны использовать конечную точку службы.   -  person Henk Holterman    schedule 22.06.2020


Ответы (1)


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

Вопрос, с которым вы связались, говорит о «длительной фоновой задаче», о чем-то, что при необходимости не должно быть частью уровня пользовательского интерфейса.

Когда вам действительно нужен токен, создайте источник с using(...) {...} вокруг этого конкретного действия. Время жизни источника не связано со временем жизни вашей страницы, поэтому страница Dispose () не подходит.


Ваш собственный примерный случай:

protected override async Task OnInitializedAsync()
{
    _uiValues = await Service.FetchCostlyValues();
}

Это либо завершится успешно, либо вызовет исключение. Единственное использование cancelToken - это токен с ограничением времени ожидания.

protected override async Task OnInitializedAsync()
{
   using (var source = new CancelationTokenSource(100))
   {
     _uiValues = await Service.FetchCostlyValues(source.Token);
   }
}

или Microsoft творит чудеса в фоновом режиме для асинхронных задач?

No.

person Henk Holterman    schedule 21.06.2020
comment
Насколько я понимаю, на стороне сервера Blazor я работаю исключительно в контексте сервера, который обрабатывает связь с пользовательским интерфейсом. Кроме того, в переопределении метода OnInitializedAsync() я делаю дальнейшие вызовы класса обслуживания, который будет обрабатывать дополнительные данные после того, как представление было отображено на клиенте (например, заполнение привязанной сетки данными). И это в том сервисном классе, где я ожидал токен. - person Kyte; 21.06.2020
comment
Почему вы ожидаете токен и как вы хотите его использовать? Как я уже сказал, обычно он вам не нужен. Но вы можете настроить его методом верхнего уровня. - person Henk Holterman; 21.06.2020
comment
А Sewrver или WebAssembly не имеют значения. В WebAsm вы также вызываете API через Http с токеном или без него. - person Henk Holterman; 21.06.2020
comment
Разве вам не нужны токены отмены в пользовательском интерфейсе, чтобы старые задачи не влияли на состояние, когда вы переходите обратно на страницу? - person Benni; 21.11.2020
comment
При переходе назад должна быть создана новая страница (объект). Предположим, вы можете создать проблемы с State Manager, но это должно быть быстро и изолированно. - person Henk Holterman; 21.11.2020