2013-09-16 14 views
8

イベント処理ロジックを持たない単一のボタンを持つシンプルなWPFプログラムがあります。次に、UIAutomationフレームワークを使用して、そのボタンを連続して何度もクリックします。最後に、私はWPFプログラムで使用されるメモリを見て、それが成長し、成長するようです。UIAutomationメモリの問題

これがなぜこのようになるのか、誰にもわかってもらえませんか?ここで

は、単純なWPFプログラム(背後にあるコードでは何も)である:ここでは

<Window x:Class="SimpleApplication.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Simple Application" 
     AutomationProperties.AutomationId="Simple Application" 
     Height="350" Width="525"> 
    <Grid> 
     <Button AutomationProperties.AutomationId="button" Height="50" Width="100">Click Me</Button> 
    </Grid> 
</Window> 

はUIAutomationのテストプログラムは次のとおりです。ここで

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 

.NETメモリプロファイラで見ると、iに表示される新しいオブジェクトn WPFアプリケーションはSystem.Threading名前空間からのものです。 WPFプログラムを単独で実行し、マウスでボタンをクリックすると、これらのオブジェクトは表示されません。

UPDATE:

私は、Visual Studioの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[] 

私はマイクロソフトにバグをも提出している:

http://connect.microsoft.com/VisualStudio/feedback/details/801209/uiautomation-memory-issue

答えて

4

マイクロソフトのカスタマーサポートに相談したところ、問題の答えが見つかりました。 WPFは内部的に、UIオートメーションイベントに3分間応答します。これを行うには、タイマーを開始します。イベントが直ちに応答されたとしても、3分が経過するまでタイマーは消えません。

したがって、問題の回避策は、タイマーが期限切れになるまで待ってからGC.Collectを実行することです。その後、メモリの問題はなくなります。偉大な修正ではありませんが、それは私たちの状況に適しています。

0

forループの外などbuttonElement、およびinvokePatternなどのオブジェクトを宣言してください。

+0

これはメモリの成長を遅くしていたようですが、それを止めるわけではありません。今度は60 MBではなく約53 MBで終了します。 – user2784456