【问题标题】:CancellationToken in Blazor Pages?Blazor 页面中的 CancellationToken?
【发布时间】:2020-10-11 11:01:37
【问题描述】:

在工作两年后,我现在在我的新工作场所遇到了 Blazor,并且在 2 年之前主要从事 ASP.NET Framework MVC 之后,我还有很多工作要做。

在 Blazor 服务器端尝试自己,我尝试应用我过去的知识,其中包括用于异步操作的取消令牌,但我找不到与 Blazor 结合使用的有关它们的太多信息。

它们仍然是最佳实践还是在某个时候已经过时? 我确实找到了this previously asked question,它建议在OnInitializedAsync() 方法上创建一个tokensource,并在Dispose() 上取消它,老实说我觉得有点粗糙。 (我需要为每个页面实现这个,你知道...... DRY)

我还找到了this Article about advanced Scenarios on 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,这里也是这种情况,但我在这里找不到任何关于此的文档。

那么,此时是否仍应使用取消令牌,或者微软是否在后台为异步任务做了一些魔术?如果是,最好的实施方式是什么?

编辑: 这是我要澄清的设置:

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

我的问题是,在代码的特定部分获取令牌的最佳方法是什么,或者它是否无关紧要,因为服务器会在连接(例如)结束时终止所有正在运行的任务?

【问题讨论】:

  • 您的编辑有帮助,但您仍然没有异常处理。你想对错误做什么?还是超时?
  • @HenkHolterman:问题是关于在 Blazor 中取消异步任务的最佳实践,而不是异常处理。我不太熟悉 Blazor 的双向二进制通信,我的艰难过程围绕“如果用户启动昂贵的异步任务(例如:生成 PDF 报告)然后导航到另一个页面怎么办?”。根据我的 MVC 知识,异步任务将继续运行并消耗资源,然后返回并被父线程上的控制器忽略或发送到客户端并被客户端拒绝。
  • 是的,对于这样的工作 (PDF),我会使用 CancelSrc。和处置()。但通常你会使用服务端点。

标签: c# asp.net .net-core async-await blazor


【解决方案1】:

CancellationToken 是服务器上的最佳实践,但您通常在 UI 层不需要它。

您链接到的问题涉及“长时间运行的后台任务”,在需要时不应成为 UI 层的一部分。

当您确实需要一个令牌时,然后围绕该特定操作创建一个带有 using(...) {...} 的 Source。源的生命周期与您的页面的生命周期无关,因此页面 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);
   }
}

或者微软是否在后台为异步任务做了一些魔法?

没有。

【讨论】:

  • 据我了解,在 Blazor 服务器端,我只在处理与 UI 通信的服务器上下文中工作。此外,在OnInitializedAsync() 方法覆盖中,我进一步调用了一个服务类,该服务类将在客户端上呈现视图后处理额外的数据(例如,用数据填充绑定网格)。它在我期望令牌的那个服务类中。
  • 为什么要使用令牌以及希望如何使用它?正如我所说,你通常不需要一个。但是你可以在顶层方法中设置一个。
  • 而 Sewrver 或 WebAssembly 几乎无关紧要。在 WebAsm 中,您还可以通过 Http 调用 API,无论是否使用令牌。
  • 您不需要 UI 中的取消标记来防止旧任务在您导航回页面时弄乱状态吗?
  • 当您“导航回来”时,应该创建一个新页面(对象)。假设您可以使用状态管理器制造问题,但这应该是罕见的和孤立的。
猜你喜欢
  • 2021-11-06
  • 2021-11-30
  • 2019-09-18
  • 1970-01-01
  • 2021-09-21
  • 2021-09-05
  • 1970-01-01
  • 2019-12-31
  • 1970-01-01
相关资源
最近更新 更多