【发布时间】:2020-04-22 07:24:43
【问题描述】:
考虑一个场景,您有一些异步工作要完成,您可以在“即发即弃”模式下运行它。此异步工作能够侦听取消,因此您将取消令牌传递给它以便能够取消它。
在给定的时间,我们可以决定请求取消正在进行的活动,方法是使用我们从中获取取消令牌的取消令牌源对象。
因为取消令牌源实现了IDisposable,所以我们应该尽可能地调用它的Dispose 方法。这个问题的重点是准确地确定何时您完成了给定的取消令牌源。
假设您决定通过在取消令牌源上调用Cancel 方法来取消正在进行的工作:在调用Dispose 之前是否需要等待正在进行的操作完成 ?
换句话说,我应该这样做吗:
class Program
{
static void Main(string[] args)
{
var cts = new CancellationTokenSource();
var token = cts.Token;
DoSomeAsyncWork(token); // starts the asynchronous work in a fire and forget manner
// do some other stuff here
cts.Cancel();
cts.Dispose(); // I call Dispose immediately after cancelling without waiting for the completion of ongoing work listening to the cancellation requests via the token
// do some other stuff here not involving the cancellation token source because it's disposed
}
async static Task DoSomeAsyncWork(CancellationToken token)
{
await Task.Delay(5000, token).ConfigureAwait(false);
}
}
或者这样:
class Program
{
static async Task Main(string[] args)
{
var cts = new CancellationTokenSource();
var token = cts.Token;
var task = DoSomeAsyncWork(token); // starts the asynchronous work in a fire and forget manner
// do some other stuff here
cts.Cancel();
try
{
await task.ConfigureAwait(false);
}
catch(OperationCanceledException)
{
// this exception is raised by design by the cancellation
}
catch (Exception)
{
// an error has occurred in the asynchronous work before cancellation was requested
}
cts.Dispose(); // I call Dispose only when I'm sure that the ongoing work has completed
// do some other stuff here not involving the cancellation token source because it's disposed
}
async static Task DoSomeAsyncWork(CancellationToken token)
{
await Task.Delay(5000, token).ConfigureAwait(false);
}
}
附加细节:我所指的代码是在 ASP.NET core 2.2 Web 应用程序中编写的,这里我使用控制台应用程序场景只是为了简化我的示例。
我在 stackoverflow 上发现了类似的问题,要求处理取消令牌源对象。一些答案表明,在某些情况下,并不真正需要处理此对象。
我对整个 IDisposable 主题的处理方法是,我总是倾向于遵守一个类的暴露契约,换一种说法,如果一个对象声称是一次性的,我更愿意在完成后总是调用 Dispose用它。我不喜欢通过依赖类的实现细节来猜测是否真的需要调用 dispose 的想法,这些实现细节可能会在未来的版本中以未记录的方式发生变化。
【问题讨论】:
标签: c# .net-core async-await task-parallel-library cancellationtokensource