2013-09-16 29 views
8

Mam prosty program WPF, który ma tylko jeden przycisk bez logiki obsługi zdarzeń. Następnie używam frameworka UIAutomation do wielokrotnego klikania tego przycisku. Na koniec patrzę na pamięć używaną przez program WPF i wydaje się, że rośnie i rośnie.Problem z pamięcią UIAutomation

Ktoś wie, dlaczego tak jest i jak mogę temu zapobiec?

Oto prosty program WPF (nic w kodzie tyłu):

<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> 

Oto program testowy 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(); 
    } 
} 

Oto wyniki z programu na moim komputerze:

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 

Patrząc na to z .NET Memory Profiler, pojawiają się nowe obiekty n Aplikacja WPF pochodzi z przestrzeni nazw System.Threading. Gdy uruchomię program WPF samoczynnie i kliknę przycisk myszką, obiekty te się nie pojawią.

UPDATE:

Próbowałem robić podobny test przy użyciu Visual Studio CodedUI i te same obiekty 8 pojawił się wyciek w takiej sytuacji, jak również. Obiekty, które wydają się wyciek to:

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[] 

Mam również składać błąd Microsoft:

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

Odpowiedz

4

Po rozmowie z obsługą klienta firmy Microsoft znaleźliśmy odpowiedź na problem. Wewnętrznie, WPF ma trzy minuty na odpowiedź na zdarzenie automatyzacji interfejsu użytkownika. Aby to zrobić, zaczyna się od licznika czasu. Wygląda na to, że nawet jeśli zdarzenie zostanie natychmiast zareagowane, licznik nie zniknie, dopóki nie miną trzy minuty.

Tak, obejście problemu polega na tym, aby poczekać do upływu czasu, a następnie wykonać GC.Collect. Wtedy problem z pamięcią zniknie. Nie jest to świetna poprawka, ale działa w naszej sytuacji.

0

Staraj się deklarować obiektów, takich jak buttonElement i invokePattern poza pętli for.

+0

To wydawało się spowolnić wzrost pamięci, ale nie zatrzymać. Teraz kończy się na około 53 MB zamiast 60 MB. – user2784456

Powiązane problemy