如果运行以下程序,我会发现Windows任务管理器中的可用内存迅速减少为零。禁止在循环中使用NSubstitute吗?
using System;
using NSubstitute;
using System.Threading;
namespace NSubstituteMemoryLeaks
{
class Program
{
static void Main(string[] args)
{
IConfig config = Substitute.For<IConfig>();
config.Value.Returns(0);
Thread th = new Thread(() => {
while (true)
{
int val = config.Value;
}
});
th.IsBackground = true;
th.Start();
Console.WriteLine("Press ENTER to stop...");
Console.ReadLine();
}
}
public interface IConfig
{
int Value { get; set; }
}
}
答案 0 :(得分:1)
模拟生成对象。问题在于程序会在短时间内创建那些对象,并且没有给Garbage Collector
足够的时间来收集对象。
它不特定于NSubstitute
。您也可以在Moq
中看到相同的行为。
您可以通过显式调用GC.Collect();
来解决。
Task.Run(() =>
{
while (true)
{
int val = config.Value;
GC.Collect();
}
});
有优缺点。您可能想在实现之前先阅读When to call GC.Collect()。
答案 1 :(得分:1)
NSubstitute记录对替代项的所有调用,因此,如果您在无限循环中调用替代项,最终将耗尽可用内存。 (如果在10,000次循环迭代后调用config.ReceivedCalls(),则应该在该列表中看到10,000个条目。)
如果您在循环中定期调用config.ClearReceivedCalls(),可能会有所帮助。
如果您有一个有界循环,这应该不成问题;一旦替代品不再使用,内存将被清除,GC会清除它。