我正在阅读@ supercat的帖子https://stackoverflow.com/a/10317035,我对以下内容有疑问:
值得注意的是,即使只与100%托管对象交互的对象也可以执行需要清理的事情(并且应该使用IDisposable)。例如,一个IEnumerator附加到一个集合" s"修改"当不再需要时,事件将需要分离。否则,除非枚举器使用一些复杂的技巧,否则只要集合在范围内,枚举器就永远不会被垃圾收集。如果集合被枚举了一百万次,那么一百万个枚举器将附加到它的事件处理程序。
我目前的代码中存在非常非常慢的内存泄漏,而且我有一段时间隔离它(需要至少12小时才能注意到私有内存中的趋势,至少需要3天时间全抛出之前会抛出一个OutOfMemoryException)。我认为它可能与@supercat提到的关于内部订阅事件的内容有关,除了我处理C#而不是VB。在生产代码中,如果while循环退出,GC会清理内存,但不会在此之前。
在以下代码中,是否有任何事件处理程序在幕后订阅?
两个循环中的任何内容都看起来像是一个托管泄漏吗?
Directory.EnumerateFiles()
是否有奇怪的内存使用行为?
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DoForeachWhile_Test
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press any key to begin. Press Escape to stop the program.");
ConsoleKeyInfo KeyPressed = Console.ReadKey();
while (KeyPressed.Key != ConsoleKey.Escape)
{
IEnumerable<string> SomeIteration = Directory.EnumerateFiles(@"C:\"); // new List<string>() { "1", "2", "3", "4", "5" };
foreach (var StringItem in SomeIteration)
{
Console.WriteLine(StringItem);
}
//Thread.Sleep(10);
Console.Clear();
if (Console.KeyAvailable)
KeyPressed = Console.ReadKey(true);
}
Console.WriteLine("Press any key to exit the program.");
Console.ReadKey();
}
}
}
答案 0 :(得分:1)
运行示例代码一天后没有泄漏。
答案 1 :(得分:0)
正如评论所说,我也认为你的循环中没有内存泄漏。
但是这一部分呢:如果RunningOTS.StartWork(...)
抛出异常怎么办?您是否应该致电RunningOTS.EndWork(...)
传递可能无效的WorkStartHandle
?
通常我会像
那样写一个像这样的块try
{
WorkStartHandle =
RunningOTS.StartWork(p_waitForStartAcknowledge: true);
// do { } while ( )
RunningOTS.EndWork(WorkStartHandle);
}
finally
{
Log
.FormattedLine(MessageScope.Nests,
"{0} :: RunToken {1}", NestID, RunningOTS);
}
但是,这可能对你不起作用,因为我不知道你的do while
是否会引发异常。可能是因为 RunningOTS.StartWork(...)
以外的行引发了异常,而您 需要调用RunningOTS.EndWork(...)
。
我最好的建议是以某种方式测试WorkStartHandle
块中finally
是否有效。假设这是一个像许多其他人一样的手柄,
if (WorkStartHandle >= 0) // valid handle?
RunningOTS.EndWork(WorkStartHandle)
......可能有效。