标签: cancellation-token

如何创建已取消的任务

我正在写一个Stream类,并在ReadAsync方法中被阻止.请看一下代码,我认为它可以更好地解释我用英语做的情况.

public override Task<int> ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken)
{
    if (!cancellationToken.IsCancellationRequested)
    {
        return _connection.ReceiveAsync(new ArraySegment<byte>(buffer, offset, count));
    }
    return // <---------------    what here?
}
Run Code Online (Sandbox Code Playgroud)

使用ILSpy我可以看到其他Stream类返回一个被取消的任务,如下所示:

return new Task<TResult>(true, default(TResult), TaskCreationOptions.None, cancellationToken); 
Run Code Online (Sandbox Code Playgroud)

但是,Task的构造函数是内部的,我无法调用它.

谷歌根本没有帮助我.

task-parallel-library async-await c#-5.0 cancellation-token

8
推荐指数
2
解决办法
2719
查看次数

退出/取消跨线程循环的技术:bool,ManualResetEvent或CancellationToken

我正在编写一个包含几个线程的程序,每个程序都有一个while循环,直到用户指定它应该停止.我想到了退出循环的几种方法,以及随后的线程,并在下面概述了这些方法.

问题

  1. 每个都有利弊吗?
  2. 是否有使用一个而不是另一个的情况?
  3. 我听说过一些人说他们更喜欢CancellationTokens退出线程.对于其他两种方法,这种方法有什么吸引力呢?

以下是方法.

bool方法

最初,我已经声明了一个bool并且刚刚声明循环运行直到用户将bool设置为false : while(running) { Thread.Sleep(10); /*do work*/ }. 然后我思索是否完全是线程安全的.如果编译器进行了一些优化并将bool移动到寄存器,该怎么办?在这种情况下,线程会看到bool的不同值.因此,我使用volatile关键字标记bool 以避免编译器优化.

ManualResetEvent方法

我的下一个方法是创建一个ManualResetEvent,并且只是说,当WaitOne()为false时bool运行:while(!mre.WaitOne(10)) {/*do work*/}.这将阻塞10ms,然后一遍又一遍地运行循环,直到我们这样做mre.Set()并且循环退出.

CancellationToken方法

我还没有尝试过这种方法,但是我读了几个人们喜欢用这种方式取消线程的地方.它显然是线程安全的.可以定义一个CancellationTokenSource,调用它cts,然后传递cts.Token给新线程运行的方法,并使用if语句检查是否已请求取消:while(!token.IsCancellationRequested) { Thread.Sleep(10); /*do work*/ }

更新1:

我发现了一篇类似的帖子,得出的结论是该MRE方法明显慢于该CancellationToken方法.有关完整信息,请参阅此处:停止线程,ManualResetEvent,volatile boolean或cancellationToken

更新2:

当谈到将这种bool方法与其他两种方法进行比较时,Eric Lippert在这里有一个很好的答案:AutoResetEvent vs. boolean来阻止一个线程

更新3:

我找到了另一条相关的信息.取消取消后,取消权限无法重置.因此,当您只想暂时取消循环,以后再次启动它时,它并不理想.为此,MRE可能会更好(因为您可以根据自己的内容设置和重置).

c# multithreading manualresetevent cancellation cancellation-token

8
推荐指数
1
解决办法
2675
查看次数

Lambda函数处理程序C#中的取消令牌

C#中的AWS Lambda函数处理程序是否提供取消令牌?

我已经阅读了AWS网站上的文档(https://docs.aws.amazon.com/lambda/latest/dg/dotnet-programming-model-handler-types.html),但在任何提及取消的地方都看不到令牌。我还检查了ILambdaContext传递给执行方法的,但是那里什么也没有。

我以前使用过Azure Functions,它们只是将它作为本文所述的函数的另一个参数传递给了我:https : //docs.microsoft.com/zh-cn/azure/azure-functions/functions-dotnet-类别库#取消令牌

c# amazon-web-services cancellation-token aws-lambda

8
推荐指数
1
解决办法
286
查看次数

OWIN Web API CancellationToken没有被调用

我正在将C#Web-Api与作为Windows服务托管的Owin一起使用,以公开读卡器实用程序。

我正在尝试使用服务器发送事件。客户端发送一个打开流的请求,并且我想在关闭流时执行逻辑(即用户关闭浏览器或调用eventSource.close()

看起来像这样:

public class CardReaderController: ApiController
{
    static ConcurrentDictionary<int, Connection> connections = new ConcurrentDictionary<int, Connection>();
    static CardReader cardReader = CardReader.Instance;

    CardReaderController() 
    {
        cardReader.OnCardRead += OnCardRead;
    }

    static void OnDisconnect(int id)
    {
        connections.TryRemove(id, out var connection);
        connection.Writer.Close();
    }

    static void OnCardRead(string cardData)
    {
        foreach(var connection in connections.Values)
            connection.Writer.WriteLine("data: " + cardData + "\n")
    }

    [HttpGet]
    public HttpResponseMessage Events(CancellationToken onDisconnect) 
    {
        ...
        int id = Request.GetHashCode();
        var response = Request.CreateResponse();
        onDisconnect.Register(() => OnDisconnect(id));

        Response.Content = new PushStreamContent((stream, content, context) …
Run Code Online (Sandbox Code Playgroud)

c# asynchronous server-sent-events asp.net-web-api cancellation-token

8
推荐指数
1
解决办法
106
查看次数

CancellationToken 与 CancellationChangeToken

CancellationToken和之间有什么区别CancellationChangeToken?我什么时候使用哪一个?

似乎它们可以用于相同的目的。我缺少什么?

cancellation-token .net-core asp.net-core

8
推荐指数
1
解决办法
2834
查看次数

.NET TPL CancellationToken内存泄漏

我开发了一个库,它实现了工作项的生产者/消费者模式.工作已经出列,并且每个出列的工作项都会出现一个单独的任务,其中包含失败和成功的延续.

任务继续在工作项完成(或失败)后重新排队.

整个库共享一个中心CancellationTokenSource,在应用程序关闭时触发.

我现在面临重大的内存泄漏.如果使用取消令牌作为参数创建任务,则任务似乎保留在内存中,直到触发取消源(并稍后处置).

这可以在此示例代码(VB.NET)中重现.主要任务是包装工作项的任务,继续任务将处理重新安排.

Dim oCancellationTokenSource As New CancellationTokenSource
Dim oToken As CancellationToken = oCancellationTokenSource.Token
Dim nActiveTasks As Integer = 0

Dim lBaseMemory As Long = GC.GetTotalMemory(True)

For iteration = 0 To 100 ' do this 101 times to see how much the memory increases

  Dim lMemory As Long = GC.GetTotalMemory(True)

  Console.WriteLine("Memory at iteration start: " & lMemory.ToString("N0"))
  Console.WriteLine("  to baseline: " & (lMemory - lBaseMemory).ToString("N0"))

  For i As Integer = 0 To 1000 ' 1001 iterations …
Run Code Online (Sandbox Code Playgroud)

.net vb.net memory-leaks task-parallel-library cancellation-token

7
推荐指数
2
解决办法
565
查看次数

将取消令牌传递给调用方法VS任务构造函数?

传递取消令牌的一种方法是:

/* Cancellation token passed as method parameter */
Task task = Task.Run( () => { LongTask(1000000, cancellationToken.Token); });
Run Code Online (Sandbox Code Playgroud)

另一种方式是:

/* Cancellation Token passed as task constructor */
Task task = Task.Run( () => { LongTask(1000000); }, cancellationToken.Token);
Run Code Online (Sandbox Code Playgroud)

有什么不同?

.net c# multithreading task-parallel-library cancellation-token

7
推荐指数
1
解决办法
1112
查看次数

为什么 IsCancellationRequested 在停止 .NET Core 3.1 中的 BackgroundService 时未设置为 true?

我已经阅读了大部分关于.NET Core 3.1 中IHostApplicationLifetime和 CancellationToken 的文章,但我找不到这不起作用的原因。

我有一个简单的BackgroundService,如下所示:

    public class AnotherWorker : BackgroundService
    {
        private readonly IHostApplicationLifetime _hostApplicationLifetime;

        public AnotherWorker(IHostApplicationLifetime hostApplicationLifetime)
        {
            _hostApplicationLifetime = hostApplicationLifetime;
        }

        public override Task StartAsync(CancellationToken cancellationToken)
        {
            Console.WriteLine($"Process id: {Process.GetCurrentProcess().Id}");
            _hostApplicationLifetime.ApplicationStarted.Register(() => Console.WriteLine("Started"));
            _hostApplicationLifetime.ApplicationStopping.Register(() => Console.WriteLine("Stopping"));
            _hostApplicationLifetime.ApplicationStopped.Register(() => Console.WriteLine("Stopped"));

            return Task.CompletedTask;
        }

        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            Console.WriteLine("Executing");
            return Task.CompletedTask;
        }

        public override async Task StopAsync(CancellationToken cancellationToken)
        {
        // This actually prints "Stop. IsCancellationRequested: False". Why?
            Console.WriteLine($"Stop. IsCancellationRequested: {cancellationToken.IsCancellationRequested}");
            await base.StopAsync(cancellationToken); …
Run Code Online (Sandbox Code Playgroud)

c# application-lifecycle cancellation-token .net-core

7
推荐指数
1
解决办法
3751
查看次数

等待取消任务的简洁方法?

我发现自己经常编写这样的代码:

try
{
    cancellationTokenSource.Cancel();
    await task.ConfigureAwait(false); // this is the task that was cancelled
}
catch(OperationCanceledException)
{
    // Cancellation expected and requested
}
Run Code Online (Sandbox Code Playgroud)

鉴于我请求取消,这是预料之中的,而且我真的希望忽略该异常。这似乎是一个常见的案例。

有没有更简洁的方法来做到这一点?我是否错过了有关取消的信息?看来应该有什么task.CancellationExpected()方法什么的。

c# task cancellation async-await cancellation-token

6
推荐指数
2
解决办法
2361
查看次数

何时将 CancellationToken 传递给控制器​​操作

根据Scalability in ASP.NET Web APIs with Cancellation Tokens,CancellationTokens 应该仅用于 HTTP GET 请求:

\n
\n

可能产生副作用的请求(例如创建、更新或删除数据)也应该保持原样,因为如果请求在错误的时刻中断,则存在损害系统数据完整性的真正风险,尤其是在该操作有多个内部步骤。这使得我们只剩下无效请求,即那些只获取数据但在完成后不修改任何内容的请求,尽管指标和日志也一样。换句话说,如果实现正确,HTTP GET 请求

\n
\n

Andrew Lock 在他的博客文章《在 ASP.NET Core MVC 控制器中使用 CancellationTokens》中也持有相同的观点:

\n
\n

如果请求修改状态,那么您可能不希望在方法中途停止执行。另一方面,如果请求没有副作用,那么您可能希望尽快停止(可能很昂贵)操作。

\n
\n

另一方面,根据在 .NET Core Web API 中使用 CancellationToken,鼓励将 CancellationToken 也传递给 POST / PUT / DELETE 请求:

\n
\n

其优点有很多,其中包括在创建、更新或删除时避免重复记录。

\n
\n

我记得在我过去使用过的几个 .NET Web 应用程序中,CancellationToken 作为参数传递给控制器​​中 GET / POST / PUT / DELETE 请求的所有操作。

\n

上述两个来源中谁是正确的。采用哪种最佳实践?就个人而言,我认为一旦创建/更新/删除数据涉及超过 1 个数据库表/1 个文件/等,向 POST、PUT 和 DELETE …

c# cancellation-token asp.net-core

6
推荐指数
0
解决办法
819
查看次数