检查CancellationToken是否已经取消
Check if CancellationToken has been cancelled
我创建了一个小演示项目来帮助我了解如何使用取消令牌。我了解您取消令牌并检查是否已请求取消,但有没有办法可以检查取消是否已实现?在下面的示例中,我不想再次 运行 Work() 直到 DoWork() 完成 运行ning.
public class Program
{
public static CancellationTokenSource tokenSource;
private static void Main(string[] args)
{
while (true)
{
Work();
}
}
public static async void Work()
{
tokenSource = new CancellationTokenSource();
Console.WriteLine("Press any key to START doing work");
Console.ReadLine();
Console.WriteLine("Press any key to STOP doing work");
DoWork(tokenSource.Token);
Console.ReadLine();
Console.WriteLine("Stopping...");
tokenSource.Cancel();
}
public static async void DoWork(CancellationToken cancelToken)
{
while (true)
{
Console.WriteLine("Working...");
await Task.Run(() =>
{
Thread.Sleep(1500);
});
if (cancelToken.IsCancellationRequested)
{
Console.WriteLine("Work Cancelled!");
return;
}
}
}
}
您通常不希望将 DoWork
函数设为 async void
——而是将其设为 async Task
。这样您就可以看到它何时完成(或被取消)。
您可能还想使用 cancelToken.ThrowIfCancellationRequested()
。这会抛出一个 OperationCanceledException
,你可以捕获它。
public class Program
{
public static CancellationTokenSource tokenSource;
private static async Task Main(string[] args)
{
while (true)
{
await Work();
}
}
public static async Task Work()
{
tokenSource = new CancellationTokenSource();
Console.WriteLine("Press any key to START doing work");
Console.ReadLine();
Console.WriteLine("Press any key to STOP doing work");
var task = DoWork(tokenSource.Token);
Console.ReadLine();
Console.WriteLine("Stopping...");
tokenSource.Cancel();
try
{
await task;
}
catch (OperationCanceledException)
{
// Task was cancelled
}
}
public static async Task DoWork(CancellationToken cancelToken)
{
while (true)
{
Console.WriteLine("Working...");
await Task.Run(() =>
{
Thread.Sleep(1500);
});
cancelToken.ThrowIfCancellationRequested();
}
}
}
此代码依赖于 C# 7 中引入的 "async main"。如果您没有此代码,您可以将 Main 方法编写为:
private static void Main(string[] args)
{
while (true)
{
Work().Wait();
}
}
如果您的所有操作都是异步且可取消的,您将充分利用 CancellationToken
。这种方式取消令牌将立即生效。您无需等待 Thread.Sleep
或其他阻塞调用完成。
public static async Task DoWork(CancellationToken cancellationToken)
{
while (true)
{
await Console.Out.WriteLineAsync("Working...");
await Task.Delay(1500, cancellationToken);
}
}
在此示例中,令牌仅传递给 Task.Delay
,因为 WriteLineAsync
在 .NET Framework 上不可取消(它在 .NET Core 上)。
取消令牌时,Task.Delay
将引发 OperationCanceledException
。
我创建了一个小演示项目来帮助我了解如何使用取消令牌。我了解您取消令牌并检查是否已请求取消,但有没有办法可以检查取消是否已实现?在下面的示例中,我不想再次 运行 Work() 直到 DoWork() 完成 运行ning.
public class Program
{
public static CancellationTokenSource tokenSource;
private static void Main(string[] args)
{
while (true)
{
Work();
}
}
public static async void Work()
{
tokenSource = new CancellationTokenSource();
Console.WriteLine("Press any key to START doing work");
Console.ReadLine();
Console.WriteLine("Press any key to STOP doing work");
DoWork(tokenSource.Token);
Console.ReadLine();
Console.WriteLine("Stopping...");
tokenSource.Cancel();
}
public static async void DoWork(CancellationToken cancelToken)
{
while (true)
{
Console.WriteLine("Working...");
await Task.Run(() =>
{
Thread.Sleep(1500);
});
if (cancelToken.IsCancellationRequested)
{
Console.WriteLine("Work Cancelled!");
return;
}
}
}
}
您通常不希望将 DoWork
函数设为 async void
——而是将其设为 async Task
。这样您就可以看到它何时完成(或被取消)。
您可能还想使用 cancelToken.ThrowIfCancellationRequested()
。这会抛出一个 OperationCanceledException
,你可以捕获它。
public class Program
{
public static CancellationTokenSource tokenSource;
private static async Task Main(string[] args)
{
while (true)
{
await Work();
}
}
public static async Task Work()
{
tokenSource = new CancellationTokenSource();
Console.WriteLine("Press any key to START doing work");
Console.ReadLine();
Console.WriteLine("Press any key to STOP doing work");
var task = DoWork(tokenSource.Token);
Console.ReadLine();
Console.WriteLine("Stopping...");
tokenSource.Cancel();
try
{
await task;
}
catch (OperationCanceledException)
{
// Task was cancelled
}
}
public static async Task DoWork(CancellationToken cancelToken)
{
while (true)
{
Console.WriteLine("Working...");
await Task.Run(() =>
{
Thread.Sleep(1500);
});
cancelToken.ThrowIfCancellationRequested();
}
}
}
此代码依赖于 C# 7 中引入的 "async main"。如果您没有此代码,您可以将 Main 方法编写为:
private static void Main(string[] args)
{
while (true)
{
Work().Wait();
}
}
如果您的所有操作都是异步且可取消的,您将充分利用 CancellationToken
。这种方式取消令牌将立即生效。您无需等待 Thread.Sleep
或其他阻塞调用完成。
public static async Task DoWork(CancellationToken cancellationToken)
{
while (true)
{
await Console.Out.WriteLineAsync("Working...");
await Task.Delay(1500, cancellationToken);
}
}
在此示例中,令牌仅传递给 Task.Delay
,因为 WriteLineAsync
在 .NET Framework 上不可取消(它在 .NET Core 上)。
取消令牌时,Task.Delay
将引发 OperationCanceledException
。