取消对客户端的长 运行 操作取消

Cancel long running operation on client cancel

我用 asp.net 核心和剃刀页面开始了我的第一个项目。 根据客户端请求,将启动一个长 运行 数据库操作。 现在我想知道,当用户离开网站时,可以取消数据库操作。

我已经用取消令牌试过了,但它永远不会被取消。

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 网格调用。 你能告诉我,为什么取消令牌没有被取消,或者我还有哪些其他选项可以检测到客户端的流产?

编辑 1

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

var dataReader = await command.ExecuteReaderAsync(cancellationToken);

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

任务设计扩展方法如下。

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

本例中取消是根据给定的时间完成的,但您可以通过调用取消方法来调用取消。

经过更多研究,我自己找到了答案。 问题是 IISExpress 中的错误,如下所述:https://github.com/aspnet/Mvc/issues/5239#issuecomment-323567952

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