C# 如何正确地取消任务并捕获OperationCanceledException?

C# 如何正确地取消任务并捕获OperationCanceledException?,c#,.net,task,C#,.net,Task,这个问题已经被问过了,但我还是不明白。。。我试图取消一项任务,但当我包含ThrowIfCancellationRequested()时,它不会被捕获,如果我不包含它,GUI将冻结 下面是我的代码,它在没有ThrowIfCancellationRequested()的情况下运行,但冻结了GUI: public void StartProcess(double myvariable) { tokenSource = new CancellationTokenSource()

这个问题已经被问过了,但我还是不明白。。。我试图取消一项任务,但当我包含ThrowIfCancellationRequested()时,它不会被捕获,如果我不包含它,GUI将冻结

下面是我的代码,它在没有ThrowIfCancellationRequested()的情况下运行,但冻结了GUI:

 public void StartProcess(double myvariable)
    {
        tokenSource = new CancellationTokenSource();
        CancellationToken token = tokenSource.Token;

        processThread = Task.Factory.StartNew(() =>
        {
            while (true)
            {
                //Do some work with myvariable

                if (token.IsCancellationRequested)
                {
                    break;
                }
            }
        }, token);
    }
对于未捕获到ThrowIfCancellationRequested()的代码,调试器将在行标记上停止。ThrowIfCancellationRequested():


我做错了什么?

通过取消请求的
是取消任务的正确方法。你需要了解的是,当你取消一项任务时,没有例外。只有任务的
状态
将设置为
已取消
。任务中的try-catch块将不起任何作用。 要获取异常,您需要在异步方法中等待任务,或者使用Wait方法等待任务完成。不建议使用Wait方法,因为在任务完成之前您将阻塞当前线程

下面是一个如何从代码中实现的建议

public static Task StartProcess(double myvariable)
{
   tokenSource = new CancellationTokenSource();
   CancellationToken token = tokenSource.Token;

   return Task.Factory.StartNew(() =>
   {
      while (true)
      {
         //Do some work with myvariable

         token.ThrowIfCancellationRequested();
      }
   }, token);
}

public async Task ExecuteProcess(double myvariable)
{
   try
   {
      await StartProcess(myvariable);
   }
   catch (OperationCanceledException ex)
   {
      Console.WriteLine("Process Thread Canceled");
   }
   catch (Exception ex)
   {
      Console.WriteLine("ERROR");
   }
}
ExecuteProcess方法演示了如何调用函数以获取异常。这样,如果从UI线程调用该方法,也可以防止GUI阻塞


我建议您阅读,以进一步了解其工作原理。

如果您通过取消安装请求调用
,则根本不需要检查
iscancellationrequest
。此外,您不需要
中断
。如果请求取消,Throw…将抛出一个异常,并且无论如何都不会进入中断。如果未请求取消,则抛出…将不会抛出,且不需要进行If检查。您应使用
标记替换完整的If块。ThrowIfCancellationRequested()哪个做的相同。
public static Task StartProcess(double myvariable)
{
   tokenSource = new CancellationTokenSource();
   CancellationToken token = tokenSource.Token;

   return Task.Factory.StartNew(() =>
   {
      while (true)
      {
         //Do some work with myvariable

         token.ThrowIfCancellationRequested();
      }
   }, token);
}

public async Task ExecuteProcess(double myvariable)
{
   try
   {
      await StartProcess(myvariable);
   }
   catch (OperationCanceledException ex)
   {
      Console.WriteLine("Process Thread Canceled");
   }
   catch (Exception ex)
   {
      Console.WriteLine("ERROR");
   }
}