取消对客户端的长 运行 操作取消
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,现在一切正常。
我用 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,现在一切正常。