1

编辑:看来我的问题患有 TL;DR 综合症。因此,您可以选择观看我发现的演示该问题的视频,而不是阅读问题:http ://www.youtube.com/watch?v=xD0mRWJazis 。视频中未显示:仅在附加调试器时发生。


我有一个使用WorkflowInvokerWindows Workflow Foundation 4.0 的应用程序。似乎当 Visual Studio 2010 调试器附加到进程时,每次我调用WorkflowInvoker.Invoke(...)进程大小都会增长大约 440 KB,直到进程增长到几 GB 并且我的计算机内存不足导致应用程序冻结和调试器崩溃(我的应用程序只需要一分钟左右即可到达那里)。未附加调试器时,不会发生内存泄漏。

Visual Studio 2010 状态栏显示

如上面的屏幕截图所示,每次调用工作流时,Visual Studio 的状态栏都会显示Loading symbols for Workflow...即使它执行相同的工作流。我猜这与内存泄漏有关。我尝试通过转到工具>选项>调试>符号并在自动加载符号下禁用符号加载,我选择了仅指定的模块并确保没有指定模块。这没有帮助,进程大小仍然稳定增长,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 秒:

包含的示例应用程序运行 30 秒,左侧没有调试器,显示稳定的 33 MB 内存占用,右侧有调试器显示内存占用以每秒 43 MB 的速度增长,仅 30 秒后达到 1.6 GB。

如您所见,内存每秒增长约 43 MB。我必须能够在调试器下运行我的应用程序。有什么建议么?

编辑:我在这里为这个问题打开了一个连接错误。

编辑:嗯,这是一个半身像。显然 Connect 仅适用于最新和最伟大的。VS2012 整整十分钟前已经 RTMed,但 connect 不再接受 VS2010 的任何反馈。我的下一站:WF4 论坛上的帖子。手指交叉。

4

3 回答 3

2

正如 Tim Lovell-Smith 在我发布的 MSDN 论坛问题中正确指出的那样,这是 .NET 4.0 中的一个已知错误,已在 .NET 4.5 中修复。幸运的是,只需安装 .NET 4.5也可以解决 Visual Studio 2010 的问题。

于 2012-10-03T21:06:39.180 回答
1

对我来说听起来像是一个Heisenbug,并不奇怪,因为@dbam987 已经指出垃圾收集器在调试时的工作方式与正常构建不同。

如果您想了解您的应用程序的内存行为,您应该测试的唯一方法是使用在附加调试器的情况下运行的发布版本。就此而言,甚至不要在没有调试的情况下从 VS2012 启动它,从资源管理器中启动它。

鉴于您指出没有调试器就没有内存泄漏,我会说您没有什么可担心的。因此,当您开始寻找一个时,这只会变成一个Heisenbug 。

于 2012-09-30T09:37:05.223 回答
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();
    }
}
于 2012-10-03T17:22:36.793 回答