gpt4 book ai didi

c# - CancellationToken 泄漏内存

转载 作者:行者123 更新时间:2023-11-30 15:53:52 26 4
gpt4 key购买 nike

我有一个计时器,每 2 秒启动 2 个任务...我在一个简单的列表中跟踪这些任务(这样我就可以在停止应用程序时等待它们完成)。

任务有效地转到数据库,运行几个更新并完成。
任务本身的运行时间不会超过一秒

...
// global variables to keep track of the running tasks.
List<Task> _tasks = new List<Task>();
CancellationTokenSource _cts = new CancellationTokenSource();

// in the timer function
private void Timer(object sender, ElapsedEventArgs e)
{
_tasks.Add( Foo1Async(_cts.Token) );
_tasks.Add( Foo2Async(_cts.Token) );
// remove the completed ones
_tasks.RemoveAll(t => t.IsCompleted);
}
...

几分钟后内存从 40Mb 增加到 130Mb,(并且攀升)...

如果我替换下面的代码并且没有替换其他

...
_tasks.Add( Foo1Async( CancellationToken.None)) );
_tasks.Add( Foo2Async( CancellationToken.None)) );
...

内存保持在稳定的 40Mb,永远不会增加。

几点

  • 我不会在测试期间取消任何任务(它们都会运行到完成)。
  • 我在测试期间没有抛出任何异常。
  • 我使用的数据库是Sqlite
  • 在两次测试中,我做的工作完全相同,唯一的区别是使用的 CancellationToken。
  • 内存似乎永远不会释放,即使我等了很长时间。
  • 计时器是一个 System.Timers.Timer,我只会在处理完计时器事件后重新启动它。
  • 我不提供任何其他 token (或 token 来源)
  • 我没有注册任何 token 取消。

如果我拍摄内存快照,CancellationCallbackInfo 的数量似乎是问题所在,但我不知道它们来自何处以及如何释放它们。

查看 .NET 源代码,回调在 CancellationTokenSource 中使用,但我不太确定添加了多少回调(或如何释放它们)。

关于当我使用 _cts.Token 与当我使用 CancellationToken.None 时可能导致内存泄漏的任何建议

最佳答案

某些 .NET DBCommand 代码存在/曾经存在问题,异步函数注册取消,但只有在出现异常时才会处理。正如您在大多数情况下注意到的那样,它只会增加列表。

此问题已在某个时间修复 last year in .NET core v2.x ,(不确定它是否会在 .NET 标准中得到修复,我使用的是 4.6.1,但它仍然是一个问题)。

我解决它的一种方法是围绕我需要的异步函数编写我自己的包装器。

您也可以调用非异步函数,(但您失去了异步函数为您提供的“取消”功能)。

关于c# - CancellationToken 泄漏内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51642225/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com