我在这里阅读@suproct的帖子https://stackoverflow.com/a/10317035我有一个关于以下的问题:
需要注意的是,即使是只与100%托管对象交互的对象也可以做需要清理的事情(并且应该使用IDisposable)。例如,附加到集合的"已修改"事件的IEnumerator在不再需要时需要将其自身分离。否则,除非枚举器使用一些复杂的技巧,否则只要集合在范围内,枚举器就永远不会被垃圾收集。如果集合被枚举一百万次,那么一百万个枚举器将附加到其事件处理程序。
目前,我的代码中有一个非常非常缓慢的内存泄漏,我很难将其隔离(至少需要12个小时才能注意到私人内存的趋势,至少需要3天才能引发OutOfMemoryException)。我认为这可能与@ssupercat提到的内部订阅事件有关,除了我处理的是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();
}
}
}
在运行示例代码一天后,没有出现任何泄漏。
正如评论所说,我也不认为循环中存在内存泄漏。
但是这部分呢:如果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)
可能会起作用。