检查CancellationToken是否已被取消

Dav*_*rpe 4 c# asynchronous cancellationtokensource

我创建了一个小演示项目来帮助我了解如何使用取消令牌。我知道您取消令牌并检查是否已请求取消,但是有没有办法可以检查取消是否已实现?在下面的示例中,我不想再次运行 Work(),直到 DoWork() 完成运行。

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

can*_*on7 6

你通常不想创建你的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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码依赖于 C# 7 中引入的“async main”。如果没有此代码,您可以将 Main 方法编写为:

private static void Main(string[] args)
{
    while (true)
    {
        Work().Wait();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @is_oz 循环结构来自OP的问题-那不是我的代码。对于“IsCancellationRequested”与“ThrowIfCancellationRequested”,它与这个玩具示例没有太大区别,但它可以让调用者区分“操作成功完成”和“操作已取消”之间的区别。由于 OP 正在尝试取消,因此这是一个值得学习的有用区别。 (2认同)
  • 这个问题让您认为“等待任务”不会等待该任务吗?这实际上就是“await”关键字的全部要点。 (2认同)