Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 检查是否已取消CancellationToken_C#_Asynchronous_Cancellationtokensource - Fatal编程技术网

C# 检查是否已取消CancellationToken

C# 检查是否已取消CancellationToken,c#,asynchronous,cancellationtokensource,C#,Asynchronous,Cancellationtokensource,我创建了一个小的演示项目来帮助我理解如何使用取消令牌。我知道您取消代币并检查是否已请求取消代币,但是否有办法检查取消是否已实现?在下面的示例中,在DoWork()完成运行之前,我不想再次运行Work() public class Program { public static CancellationTokenSource tokenSource; private static void Main(string[] args) { while (true

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

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无效
——而是将其设置为
async任务
。这样您就可以看到它何时完成(或被取消)

您可能还想使用
cancelToken.ThrowIfCancellationRequested()
。这会抛出一个
操作取消异常
,您可以捕获该异常

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”。如果没有此选项,可以将主方法编写为:

private static void Main(string[] args)
{
    while (true)
    {
        Work().Wait();
    }
}

如果所有操作都是异步且可取消的,那么您将充分利用
CancellationToken
。这样取消令牌将立即生效。您不必等待
线程.Sleep
或其他阻塞调用完成

public static async Task DoWork(CancellationToken cancellationToken)
{
    while (true)
    {
        await Console.Out.WriteLineAsync("Working...");
        await Task.Delay(1500, cancellationToken);
    }
}
在本例中,令牌仅传递给
Task.Delay
,因为该令牌在.NET Framework上不可取消(在.NET Core上)


任务将引发
操作取消异常
。取消令牌时延迟

不要使用
异步无效
。使用
异步任务
。生成的
任务
可以等待(如果已取消,则引发异常)或根据您的意愿显式检查是否完成。@循环结构是否来自OP的问题-这不是我的代码。对于
IsCancellationRequested
vs
throwifccancellationrequested
,它与这个玩具示例没有多大区别,但它让调用方知道“操作成功完成”和“操作被取消”之间的区别。因为OP是在玩取消游戏,所以这是一个很有用的区别,在这里可以很好地使用。是什么让你认为它不会在
等待任务时等待呢?
任务.wait()
也应该抛出一个异常——但这是一个不会被注意的
聚合异常
,这个问题会让你认为
等待任务
不会等待任务吗?这就是
wait
关键字的全部要点。@canton7获得206票的答案意味着等待任务不会等待任务完成。再一次,我完全复制了你的代码并运行了它,它按照你说的那样工作。我在代码中的某个地方犯了一个错误,所以道歉!!再次感谢你的回答