在c#中使用CancellationToken取消任务

目录

介绍:

简单举例

IsCancellationRequested

ThrowIfCancellationRequested

在控制器中使用

 通过异步方法的参数使用cancellationToken

api结合ThrowIfCancellationRequested()


介绍:

CancellationToken是.NET中用于协调取消操作的结构。它通常用于多线程操作,例如任务和线程等。当你启动一个新的任务或线程时,你可以传递一个CancellationToken给它,然后在其他线程中,你可以使用这个token来请求取消操作。

  • 属性:IsCancellationRequested,它的返回值是bool类型,即表示当前任务是否被取消,当调用CancellationTokenSource的Cancel方法时,与之关联的所有CancellationToken的IsCancellationRequested属性将返回true。
  • 方法:ThrowIfCancellationRequested,如果IsCancellationRequested为true,那么它将抛出一个OperationCanceledException异常。这是一种在任务中响应取消请求的常见方式。

例如,你可能有一个长时间运行的任务,你希望用户能够取消。你可以传递一个CancellationToken给这个任务,然后在任务的代码中定期检查IsCancellationRequested属性,或者调用ThrowIfCancellationRequested方法。如果用户请求取消操作,那么你的任务代码将能够响应这个请求。

简单举例

下面用几个简单的例子来使用IsCancellationRequested属性与ThrowIfCancellationRequested方法,更直观的展示他们的用法,在CancellationToken中我们可以直接使用Cancel()方法来取消操作,但是为了演示方便,我们下面的例子使用的都是CancelAfter()来进行延迟关闭

IsCancellationRequested

我们创建一个CancellationTokenSource对象,然后通过CancelAfter(5000)设置一个5秒的取消延迟。然后写一个无限循环,在循环中打印"任务执行中!"(假装在执行任务)!5秒钟后,CancelAfter方法会触发取消请求,这时cts.IsCancellationRequested属性会变为true。然后就会打印"任务被取消!",并跳出循环。如下图所示

    public static void Main(string[] args)
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        cts.CancelAfter(5000);
        while (true)
        {
            Console.WriteLine("任务执行中!");
            if (cts.IsCancellationRequested)
            {
                Console.WriteLine("任务被取消!");
                break;
            }
        }
    }

在c#中使用CancellationToken取消任务_第1张图片

ThrowIfCancellationRequested

将刚刚的代码修改一下,换成使用ThrowIfCancellationRequested(),方法执行后,还是会在控制台打印"任务执行中!",5秒钟后,CancelAfter方法触发取消请求,于是执行到ThrowIfCancellationRequested()的时候抛出了一个异常,操作被取消了!

    public static void Main(string[] args)
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        cts.CancelAfter(5000);
        while (true)
        {
            Console.WriteLine("任务执行中!");
            cts.Token.ThrowIfCancellationRequested();
        }
    }

在c#中使用CancellationToken取消任务_第2张图片

在控制器中使用

在ASP.NET Core中,CancellationToken是一个可选参数,可以被添加到控制器的动作方法中。当客户端请求被关闭或取消时,ASP.NET Core会自动取消关联的CancellationToken。

这是因为ASP.NET Core的内部机制。当客户端发送一个请求到服务器,服务器会为这个请求创建一个CancellationToken,并且当客户端关闭连接时,服务器会自动调用CancellationToken的Cancel方法,以便通知应用程序请求已经被取消。

因此,我们可以直接在Controller中加入CancellationToken参数,如下图,这是我的一个ai识别项目,他会将收到的图片作为请求体,调用我部署在服务器上的ai识别api,如果用户通过网页,上传了一张图片进行ai识别,但是因为识别时间太长了,他不想等待并且把网页关了,此时我的后台还在傻傻的进行图片识别,势必会造成资源的浪费,下面我们就来改造一下他!

在c#中使用CancellationToken取消任务_第3张图片

在上面我们调用PutPhoto的时候参数中添加了controller中拿到的cancellationToken,因此这边方法中的参数也加上CancellationToken cancellationToken来接,如下图,上面的代码都是对请求体进行组装,我们重点看最下面这一行。

var response = await client.ExecuteAsync(request);

 通过异步方法的参数使用cancellationToken

在c#中使用CancellationToken取消任务_第4张图片

Ctrl + 左键 点击 ExecuteAsync

我们查看一下RestClient的ExecuteAsync方法,可以看见他是有一个可选参数cancellationToken,这意味这我们又可以直接把在controller中拿到的cancellationToken继续丢进去。

在c#中使用CancellationToken取消任务_第5张图片

因此,我们把最后一句代码改成,然后我在执行这一行代码之前,打一个断点。

var response = await client.ExecuteAsync(request,cancellationToken);

 在执行这行代码之前,我将浏览器关闭了,然后再继续下一步

 我们在返回结果中看到,错误信息中提示:A task was canceled,一个任务被取消,其实哪怕是我的请求在进行中,只要一关闭浏览器,任务就会立马结束,但是因为我服务器的响应速度太快了,不好实现这个演示!

在c#中使用CancellationToken取消任务_第6张图片

api结合ThrowIfCancellationRequested()

假设你现在的场景中异步方法并没有cancellationToken参数,那么你可以结合我们上面演示中使用的ThrowIfCancellationRequested()来取消操作。请求取消时,它会抛出一个异常OperationCanceledException,这样你就可以在你的代码中捕获这个异常并进行相应的处理。

try
{
    var response = await client.ExecuteAsync(request);
    // 在这里检查取消标记
    cancellationToken.ThrowIfCancellationRequested();
}
catch (OperationCanceledException)
{
    // 这里处理取消操作的逻辑
}

要注意的是,这种方式只能取消还没有开始的操作。如果ExecuteAsync方法已经开始执行,那么这个取消请求就无法停止它,因此如果异步方法可以支持传参cancellationToken的话,我们还是首选使用传参的方法!

你可能感兴趣的:(c#,c#,.netcore)