2013-09-16 72 views
8

Tôi có một chương trình WPF đơn giản chỉ có một nút duy nhất không có logic xử lý sự kiện. Sau đó, tôi sử dụng khung UIAutomation để nhấp vào nút đó nhiều lần liên tiếp. Cuối cùng, tôi nhìn vào bộ nhớ được sử dụng bởi chương trình WPF và nó dường như phát triển và phát triển.Bộ nhớ UIAutomation Vấn đề

Bất kỳ ai biết tại sao trường hợp này xảy ra và cách tôi có thể ngăn điều này xảy ra?

Dưới đây là chương trình WPF đơn giản (không có gì trong đoạn code phía sau):

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

Đây là chương trình thử nghiệm 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(); 
    } 
} 

Dưới đây là kết quả từ các chương trình trên máy tính của tôi:

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 

Nhìn vào nó bằng .NET Memory Profiler, các đối tượng mới xuất hiện n ứng dụng WPF là từ không gian tên System.Threading. Khi tôi chạy chương trình WPF của chính nó và bấm vào nút bằng chuột, các đối tượng này không xuất hiện.

UPDATE:

Tôi đã thử làm một bài kiểm tra tương tự như sử dụng CodedUI Visual Studio, và 8 đối tượng cùng xuất hiện để rò rỉ trong tình huống đó là tốt. Các đối tượng có vẻ như bị rò rỉ bao gồm:

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

Tôi cũng đã gửi một lỗi cho Microsoft:

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

Trả lời

4

Sau khi nói chuyện với bộ phận hỗ trợ khách hàng của Microsoft, chúng tôi đã tìm thấy câu trả lời cho vấn đề. Bên trong, WPF tự cung cấp ba phút để phản hồi sự kiện Tự động hóa giao diện người dùng. Để làm điều này, nó bắt đầu tắt một bộ đếm thời gian. Có vẻ như ngay cả khi sự kiện được trả lời ngay lập tức, bộ hẹn giờ không biến mất cho đến sau ba phút.

Vì vậy, giải pháp cho vấn đề là chờ cho đến khi hết thời gian và sau đó thực hiện GC.Collect. Sau đó, vấn đề bộ nhớ sẽ biến mất. Không phải là một sửa chữa tuyệt vời, nhưng nó hoạt động cho tình hình của chúng tôi.

0

Hãy thử để khai báo các đối tượng như buttonElement, và invokePattern bên ngoài của vòng lặp for.

+0

Điều đó dường như làm chậm tốc độ tăng trưởng của bộ nhớ, nhưng không dừng lại. Bây giờ nó kết thúc vào khoảng 53 MB thay vì 60 MB. – user2784456