【问题标题】:Cancel long running operation on client cancel取消客户端上的长时间运行操作取消
【发布时间】:2019-08-09 15:34:18
【问题描述】:

我的第一个项目是使用 asp.net core 和 razor pages 开始的。 在客户端请求时,将启动长时间运行的数据库操作。 现在我想识别,当用户离开网站时,可以取消数据库操作。

我用cancellationToken尝试过,但它永远不会被取消。

public async Task<JsonResult> OnPostReadAsync([DataSourceRequest] DataSourceRequest request, CancellationToken cancellationToken)
{
    var messages = await _logMessageService.GetLogMessagesAsync(request, cancellationToken);

    return new JsonResult(messages.ToDataSourceResult(request));
}

函数被 Telerik Kendo UI Grid 调用。 你能告诉我,为什么取消令牌没有被取消,或者我必须有哪些其他选项来检测客户的流产?

编辑 1

我将 Token 传递给 NpgsqlCommand 的这个函数调用:

var dataReader = await command.ExecuteReaderAsync(cancellationToken);

【问题讨论】:

  • AFAIK 只能处理停止/刷新,见andrewlock.net/…
  • 您是否尝试过使用HttpContext.RequestAborted 取消令牌?像这样:var messages = await _logMessageService.GetLogMessagesAsync(request, HttpContext.RequestAborted);
  • 看不到你的日志消息服务是不可能的。取消令牌并不神奇,在某处有代码实际检查令牌状态并在取消时中止。简单地将它传递给一个方法并不能实现任何效果,除非它在工作期间被该方法实际使用。
  • 嘿,克里斯,我将令牌传递给 NpgsqlCommand 并调用函数 ExecuteReader。
  • 嘿 Rufo 和 Alberto,正如在 Rufos 链接中提到的那样,我的取消令牌参数将自动绑定到 HttpContext.RequestAborted 令牌。所以这也不会被取消。

标签: c# asp.net-core razor-pages cancellation-token


【解决方案1】:

要取消 IO 绑定,即长时间运行的任务,以下是您可以执行的代码,我使用 CLR 书从 C# 中获得。

设计任务扩展方法如下。

private static async Task<TResult> WithCancellation<TResult>(this Task<TResult> originalTask,
CancellationToken ct) {
   // Create a Task that completes when the CancellationToken is canceled
   var cancelTask = new TaskCompletionSource<Void>();
   // When the CancellationToken is canceled, complete the Task
  using (ct.Register(
     t => ((TaskCompletionSource<Void>)t).TrySetResult(new Void()), cancelTask)) {
    // Create a Task that completes when either the original or
    // CancellationToken Task completes
    Task any = await Task.WhenAny(originalTask, cancelTask.Task);
    // If any Task completes due to CancellationToken, throw OperationCanceledException
     if (any == cancelTask.Task) ct.ThrowIfCancellationRequested();
  }
  // await original task (synchronously); if it failed, awaiting it
  // throws 1st inner exception instead of AggregateException
 return await originalTask;
}

如以下示例代码所示,您可以使用上面设计的扩展方法取消它。

public static async Task Go() {
   // Create a CancellationTokenSource that cancels itself after # milliseconds
   var cts = new CancellationTokenSource(5000); // To cancel sooner, call cts.Cancel()
   var ct = cts.Token;
   try {
    // I used Task.Delay for testing; replace this with another method that returns a Task
     await Task.Delay(10000).WithCancellation(ct);
     Console.WriteLine("Task completed");
   }
   catch (OperationCanceledException) {
    Console.WriteLine("Task cancelled");
  }
}

在这个例子中取消是根据给定时间完成的,但是你可以通过调用取消方法来调用取消。

【讨论】:

    【解决方案2】:

    因此,经过更多研究,我自己找到了答案。 问题是这里提到的 IISExpress 中的一个错误:https://github.com/aspnet/Mvc/issues/5239#issuecomment-323567952

    我切换到 Kestrel,现在一切正常。

    【讨论】:

      猜你喜欢
      • 2011-03-03
      • 1970-01-01
      • 2012-04-03
      • 1970-01-01
      • 2012-02-13
      • 2021-10-29
      • 1970-01-01
      • 1970-01-01
      • 2013-01-21
      相关资源
      最近更新 更多