我正在写一个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?
}
使用ILSpy我可以看到其他Stream类返回一个被取消的任务,如下所示:
return new Task<TResult>(true, default(TResult), TaskCreationOptions.None, cancellationToken); 
但是,Task的构造函数是内部的,我无法调用它.
谷歌根本没有帮助我.
我正在编写一个包含几个线程的程序,每个程序都有一个while循环,直到用户指定它应该停止.我想到了退出循环的几种方法,以及随后的线程,并在下面概述了这些方法.
问题
以下是方法.
该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
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#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) …c# asynchronous server-sent-events asp.net-web-api cancellation-token
CancellationToken和之间有什么区别CancellationChangeToken?我什么时候使用哪一个?
似乎它们可以用于相同的目的。我缺少什么?
我开发了一个库,它实现了工作项的生产者/消费者模式.工作已经出列,并且每个出列的工作项都会出现一个单独的任务,其中包含失败和成功的延续.
任务继续在工作项完成(或失败)后重新排队.
整个库共享一个中心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 ….net vb.net memory-leaks task-parallel-library cancellation-token
传递取消令牌的一种方法是:
/* Cancellation token passed as method parameter */
Task task = Task.Run( () => { LongTask(1000000, cancellationToken.Token); });
另一种方式是:
/* Cancellation Token passed as task constructor */
Task task = Task.Run( () => { LongTask(1000000); }, cancellationToken.Token);
有什么不同?
.net c# multithreading task-parallel-library cancellation-token
我已经阅读了大部分关于.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); …我发现自己经常编写这样的代码:
try
{
    cancellationTokenSource.Cancel();
    await task.ConfigureAwait(false); // this is the task that was cancelled
}
catch(OperationCanceledException)
{
    // Cancellation expected and requested
}
鉴于我请求取消,这是预料之中的,而且我真的希望忽略该异常。这似乎是一个常见的案例。
有没有更简洁的方法来做到这一点?我是否错过了有关取消的信息?看来应该有什么task.CancellationExpected()方法什么的。
根据Scalability in ASP.NET Web APIs with Cancellation Tokens,CancellationTokens 应该仅用于 HTTP GET 请求:
\n\n\n可能产生副作用的请求(例如创建、更新或删除数据)也应该保持原样,因为如果请求在错误的时刻中断,则存在损害系统数据完整性的真正风险,尤其是在该操作有多个内部步骤。这使得我们只剩下无效请求,即那些只获取数据但在完成后不修改任何内容的请求,尽管指标和日志也一样。换句话说,如果实现正确,HTTP GET 请求。
\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# ×7
.net ×2
.net-core ×2
asp.net-core ×2
async-await ×2
cancellation ×2
asynchronous ×1
aws-lambda ×1
c#-5.0 ×1
memory-leaks ×1
task ×1
vb.net ×1