我可以在取消CancellationTokenSource
之前处置Task
吗?如果没有,为什么?
代码1 (摘自Task Cancellation。为简化起见,我做了一些小的更改)似乎建议在处置Task
之前先等待CancellationTokenSource
。如果是这样,包含Dispose
的类的CancellationTokenSource
方法将比我希望的更加复杂。
在我的PC上,代码2 也似乎正常工作。我可以改用这种模式吗?
代码1:取消完成后处理
[STAThread]
private static void Main() {
var tokenSource2 = new CancellationTokenSource();
var task = DoAsync(tokenSource2.Token);
tokenSource2.Cancel();
tokenSource2 = null;
try {
task.Wait();
}
catch (AggregateException e) {
foreach (var v in e.InnerExceptions)
Console.WriteLine(e.Message + " " + v.Message);
}
finally {
tokenSource2.Dispose();
}
Console.ReadKey();
}
private static async Task DoAsync(CancellationToken token) {
while (true) {
await Task.Delay(10000).ConfigureAwait(true);
token.ThrowIfCancellationRequested();
}
}
代码2:取消之前先处理
[STAThread]
private static void Main() {
var tokenSource2 = new CancellationTokenSource();
var task = DoAsync(tokenSource2.Token);
tokenSource2.Cancel();
tokenSource2.Dispose();
try {
task.Wait();
}
catch (AggregateException e) {
foreach (var v in e.InnerExceptions)
Console.WriteLine(e.Message + " " + v.Message);
}
finally {
//// tokenSource2.Dispose();
}
Console.ReadKey();
}
private static async Task DoAsync(CancellationToken token) {
while (true) {
await Task.Delay(10000).ConfigureAwait(true);
token.ThrowIfCancellationRequested();
}
}
实际上,我想知道是否必须通过Wait
方法Dispose
来取消任务。
public class Class1 : IDisposable {
//// tokenSource for calculationTask
private CancellationTokenSource tokenSource;
//// background calculation task
private Task calculationTask;
public void Dispose() {
tokenSource?.Cancel();
//// calculationTask.Wait(); Should I wait for task completion?
tokenSource?.Dispose();
tokenSource = null;
calculationTask = null;
}
}
答案 0 :(得分:1)
我不太了解您要做什么,但是让我们看一下事实。
处置令牌源不会影响令牌,但是,在任务完成之前处置令牌是没有意义的。另外,如果可用,请始终使用using语句。
此外,您可以在C#7.1或更高版本中使用异步主要方法。只需在构建设置中更改高级选项即可。
我认为这似乎是您更常用的方式
// use async all the way down
static async Task Main(string[] args)
{
// using using using
using (var tokenSource2 = new CancellationTokenSource())
{
try
{
var task = DoAsync(tokenSource2.Token);
// test cancel
tokenSource2.Cancel();
// await anything you need.
await Task.WhenAll(task);
}
// catch CanceledException
catch (OperationCanceledException)
{
Console.WriteLine("Canceled");
}
// notice we get normal exceptions and not aggregates
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Console.ReadKey();
}
private static async Task DoAsync(CancellationToken token)
{
// pass your toke in to anything that needs it
await Task.Delay(10000,token).ConfigureAwait(true);
token.ThrowIfCancellationRequested();
}