简体   繁体   English

取消客户端上的长期运行取消

[英]Cancel long running operation on client cancel

I started my first project with asp.net core and razor pages. 我从asp.net核心和剃须刀页面开始了我的第一个项目。 On a client request, a long running database operation will be started. 应客户请求,将启动长时间运行的数据库操作。 Now i want to recognize, when the user leaves the website, so the database operation can be cancelled. 现在我想知道,当用户离开网站时,可以取消数据库操作。

I've tried it with a cancellationToken, but it will never be cancelled. 我已经使用了cancelToken进行了尝试,但是它永远不会被取消。

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

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

The function get called by an Telerik Kendo UI Grid. 该功能由Telerik Kendo UI网格调用。 Can you tell me, why the cancellation token don't get cancelled, or what other options I have to detect a abortion by the client? 您能告诉我,为什么取消令牌没有被取消,或者我还必须通过其他哪些选项来检测客户端是否中止?

Edit 1 编辑1

I pass the Token through to this function call of a NpgsqlCommand: 我将令牌传递给NpgsqlCommand的此函数调用:

var dataReader = await command.ExecuteReaderAsync(cancellationToken);

To cancel IO bound ie task which is running long , following is code that you can do which i got form the C# with CLR book. 要取消IO绑定,即运行时间长的任务,下面是您可以执行的代码,这些代码是我用CLR书从C#中获得的。

Design extension method for task as below. 设计任务扩展方法如下。

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

as given in following example code you can cancel it by using extension method designed above. 如以下示例代码所示,您可以使用上面设计的扩展方法将其取消。

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

In this example cancellation done based on given time , but you can call cancellation by calling cancel method. 在此示例中,取消是基于给定的时间完成的,但是您可以通过调用cancel方法来调用取消。

So I found the answer myself after some more research. 因此,经过更多研究,我自己找到了答案。 The problem is a bug in IISExpress as mentioned here: https://github.com/aspnet/Mvc/issues/5239#issuecomment-323567952 问题是这里提到的IISExpress中的错误: https : //github.com/aspnet/Mvc/issues/5239#issuecomment-323567952

I switched to Kestrel and now everything works as expected. 我切换到Kestrel,现在一切正常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM