编辑:看来我的问题患有TL; DR综合症。因此,您可以选择查看我发现的显示问题的视频,而不是阅读问题:http://www.youtube.com/watch?v=xD0mRWJazis。视频中未显示:仅在附加调试器时发生。
我有一个使用Windows Workflow Foundation 4.0中的WorkflowInvoker
的应用程序。似乎Visual Studio 2010调试器附加到进程,每次调用WorkflowInvoker.Invoke(...)
时,进程大小增加大约440 KB,直到进程增长到几千兆字节并且我的计算机内存不足导致应用程序冻结和调试器崩溃(我的应用程序只需要一分钟左右到达那里)。 未附加调试器时,不会发生内存泄漏。
如上面的屏幕截图所示,每次调用工作流时,Visual Studio的状态栏都会显示工作流的加载符号... ,即使它执行相同的工作流程。我猜这与内存泄漏有关。我尝试通过转到工具>来禁用符号加载选项> 调试> 符号和自动加载符号我选择仅指定模块并确保没有指定模块。这没有帮助,流程大小仍然稳步增长,Visual Studio仍然加载了工作流符号。
以下是重现问题的最小代码。使用和不使用调试器运行它时查看任务管理器(小心,它在调试时会非常快地占用内存!):
var workflow = new WorkflowInvoker(new Sequence());
while (true)
workflow.Invoke(); //// Memory leak! ////
下面列出了一个更加扩展的控制台程序,用于在显示内存消耗时显示问题。它每秒只运行大约100个空工作流程。尝试运行它而不进行调试( Ctrl + F5 )并将其与调试运行( F5 )进行比较。你会马上看到差异。如果您不想运行该示例,我将结果包含在下面的屏幕截图中。
using System;
using System.Activities;
using System.Activities.Statements;
using System.Diagnostics;
using System.Threading;
class Program
{
static Timer Timer = new Timer(PrintMemory, null, 1000, 1000);
static double PreviousSize;
static void Main(string[] args)
{
Console.WriteLine("Debugger {0} attached.",
Debugger.IsAttached ? "IS" : "is NOT");
var workflow = new WorkflowInvoker(new Sequence());
while (true)
{
workflow.Invoke(); //// Memory leak! ////
Thread.Sleep(10);
}
}
static void PrintMemory(object o)
{
double newSize = Process.GetCurrentProcess().PrivateMemorySize64 / 1048576d;
Console.WriteLine("Grew by {0,5:F2} MB (total {1,7:F2} MB)",
newSize - PreviousSize, newSize);
PreviousSize = newSize;
}
}
这是一个没有调试的程序运行30秒:
如您所见,内存每秒增长约43 MB。我必须能够在调试器下运行我的应用程序。有什么建议吗?
编辑:我已针对此问题here打开了Connect错误。
编辑:这是一个半身像。显然Connect仅适用于最新和最好的。 VS2012整整十分钟都有RTMed,但是连接不再接受VS2010的任何反馈。我的下一站:a post on the WF4 forum。手指交叉。
答案 0 :(得分:2)
正如Tim Lovell-Smith在MSDN论坛question I posted中正确指出的那样,这是.NET 4.0中已知的错误,已在.NET 4.5中修复。幸运的是,简单地installing .NET 4.5也解决了Visual Studio 2010的问题。
答案 1 :(得分:1)
对我来说听起来像Heisenbug并且不是很令人惊讶,因为@ dbam987已经指出垃圾收集器在调试时的工作方式与正常构建不同。
如果您想了解应用的内存行为,那么您应该测试的唯一方法是使用附带的调试器运行发布构建而不是。就此而言,如果没有调试,甚至不从VS2012启动它,从资源管理器启动它。
鉴于您指出没有调试器没有内存泄漏,我会说您没有什么可担心的。所以当你开始寻找一个时,这只会变成Heisenbug。
答案 2 :(得分:0)
尝试使用 WorkflowApplication 组件而不是 WorkflowInvoker 启动工作流程。其设置与使用 WorkflowInvoker 非常相似。
using System;
using System.Activities.Statements;
using System.Threading;
public class Program
{
public static void Main(string[] args)
{
// Setup the sample workflow.
var workflow = new Sequence
{
Activities =
{
new WriteLine { Text = "Hello World!" },
new Delay { Duration = TimeSpan.FromSeconds(3) },
new WriteLine { Text = "Done!" }
}
};
// Setup the workflow host.
var syncWorkflowEvent = new AutoResetEvent(false);
var workflowApp = new WorkflowApplication(workflow);
workflowApp.Completed = eventArgs => syncWorkflowEvent.Set();
workflowApp.Run();
syncWorkflowEvent.WaitOne();
}
}