C# UIA自动化内存问题

C# UIA自动化内存问题,c#,wpf,memory-leaks,ui-automation,C#,Wpf,Memory Leaks,Ui Automation,我有一个简单的WPF程序,它只有一个按钮,没有事件处理逻辑。然后,我使用UIAutomation框架连续多次单击该按钮。最后,我看一下WPF程序使用的内存,它似乎在不断增长 有人知道为什么会这样,我怎样才能防止这种情况发生吗 下面是简单的WPF程序(代码中没有任何内容): 使用.NET内存探查器查看,WPF应用程序中出现的新对象来自System.Threading命名空间。当我自己运行WPF程序并用鼠标单击按钮时,这些对象不会出现 更新: 我试着用VisualStudio的CodedUI做了一个

我有一个简单的WPF程序,它只有一个按钮,没有事件处理逻辑。然后,我使用UIAutomation框架连续多次单击该按钮。最后,我看一下WPF程序使用的内存,它似乎在不断增长

有人知道为什么会这样,我怎样才能防止这种情况发生吗

下面是简单的WPF程序(代码中没有任何内容):

使用.NET内存探查器查看,WPF应用程序中出现的新对象来自System.Threading命名空间。当我自己运行WPF程序并用鼠标单击按钮时,这些对象不会出现

更新:

我试着用VisualStudio的CodedUI做了一个类似的测试,同样的8个对象在这种情况下也出现了泄漏。出现泄漏的对象包括:

System.Threading.CancellationTokenSource
System.Threading.TimerQueueTimer
System.Threading.SparselyPopulatedArray<CancellationCallbackInfo>[]
System.Threading.Timer
System.Threading.TimerHolder
System.Threading.SparselyPopulatedArray<CancellationCallbackInfo>
System.Threading.SparselyPopulatedArrayFragment<CancellationCallbackInfo>
System.Threading.CancellationCallbackInfo[]
System.Threading.CancellationTokenSource
System.Threading.TimerQueueTimer
System.Threading.SparselyPopulatedArray[]
系统线程计时器
System.Threading.TimerHolder
System.Threading.SparselyPopulatedArray
System.Threading.SparselyPopulatedArrayFragment
System.Threading.CancellationCallbackInfo[]
我还向Microsoft提交了一个错误:


尝试在for循环之外声明对象,如buttonElement和invokePattern

与Microsoft客户支持人员交谈后,我们找到了问题的答案。在内部,WPF给自己三分钟时间来响应UI自动化事件。为此,它启动一个计时器。即使事件立即响应,计时器也不会在三分钟后消失


因此,解决此问题的方法是等待计时器过期,然后执行GC.Collect。然后内存问题就会消失。这不是一个很好的解决办法,但它对我们的情况有效。

这似乎会减缓内存增长,但不会阻止内存增长。现在它结束于53MB而不是60MB。一些研究:然后检查元素。调用在SynchronizedInputAdapter(ISynchronizedInputProvider)上调用cancel需要3分钟的超时时间。
class Program
{
    static void Main(string[] args)
    {
        string appPath = @"..\..\..\SimpleApplication\bin\Debug\SimpleApplication.exe";
        string winAutoId = "Simple Application";
        string buttonAutoId = "button";

        using (Process process = Process.Start(new ProcessStartInfo(appPath)))
        {
            Thread.Sleep(TimeSpan.FromSeconds(1));

            AutomationElement winElement = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, winAutoId));

            for (int i = 0; i < 1001; i++)
            {
                AutomationElement buttonElement = winElement.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, buttonAutoId));

                InvokePattern invokePattern = (InvokePattern)buttonElement.GetCurrentPattern(InvokePattern.Pattern);
                invokePattern.Invoke();

                process.Refresh();
                long totalMemory = process.WorkingSet64 + process.PagedMemorySize64;

                if (i % 100 == 0)
                {
                    Console.WriteLine("Memory = {0} MB", ((double)totalMemory) / (1024 * 1024));
                }
            }

            WindowPattern windowPattern = (WindowPattern)winElement.GetCurrentPattern(WindowPattern.Pattern);
            windowPattern.Close();
        }

        Console.WriteLine();
        Console.WriteLine("Press Enter to Continue...");
        Console.ReadLine();
    }
}
Memory = 38.20703125 MB
Memory = 42.9296875 MB
Memory = 45.00390625 MB
Memory = 47.04296875 MB
Memory = 51.9296875 MB
Memory = 52.2890625 MB
Memory = 52.41015625 MB
Memory = 55.70703125 MB
Memory = 55.70703125 MB
Memory = 57.21484375 MB
Memory = 59.09375 MB
System.Threading.CancellationTokenSource
System.Threading.TimerQueueTimer
System.Threading.SparselyPopulatedArray<CancellationCallbackInfo>[]
System.Threading.Timer
System.Threading.TimerHolder
System.Threading.SparselyPopulatedArray<CancellationCallbackInfo>
System.Threading.SparselyPopulatedArrayFragment<CancellationCallbackInfo>
System.Threading.CancellationCallbackInfo[]