2009-12-17 27 views
6

Tôi đang tìm kiếm thông qua một ứng dụng WPF tìm kiếm một rò rỉ bộ nhớ (sử dụng ANTS Memory Profiler 5.1) và tôi tiếp tục nhìn thấy một số trang và điều khiển chiếm bộ nhớ khi chúng không được.Tôi có bị rò rỉ bộ nhớ trong Điều hướng WPF không?

Vì vậy, tôi đi đến Object Retention Graph và để xem những gì được giữ cho chúng xung quanh, và tôi tiếp tục nhìn thấy điều này cho mỗi trang:

Object Retention Graph http://img683.imageshack.us/img683/3013/ants.jpg

Có điều là, tôi có KeepAlive thiết lập để sai trên mỗi trang và tôi không nghĩ rằng một thuộc tính như vậy tồn tại trên các điều khiển của người dùng.

Bất cứ ai có thể cho tôi biết tôi nên tìm kiếm điều gì? Đây có phải là ngay cả một rò rỉ bộ nhớ hoặc là hành vi bình thường này cho một ứng dụng WPF?

Trả lời

8

Có, theo những gì bạn đã cung cấp, bạn bị rò rỉ bộ nhớ. Khi bạn tìm thấy chuỗi tham chiếu, và nó không có trong mã của bạn, cách dễ nhất để đi là ... Reflector.

Hình ảnh cho biết: JournalEntryKeepAlive._keepAliveRoot trường chứa tham chiếu đến đối tượng. Chúng ta hãy đi vào Reflector và xem làm thế nào anh chàng này được nối với đối tượng của chúng tôi.

Lần này thật dễ dàng và tất cả các dấu vết đều dẫn đến chức năng NavigationService.MakeJournalEntry() và sau đó đến NavigationService.IsContentKeepAlive(). Dưới đây là:

internal bool IsContentKeepAlive() 
{ 
    bool keepAlive = true; 
    DependencyObject dependencyObject = this._bp as DependencyObject; 
    if (dependencyObject != null) 
    { 
     keepAlive = JournalEntry.GetKeepAlive(dependencyObject); 
     if (!keepAlive) 
     { 
      PageFunctionBase base2 = dependencyObject as PageFunctionBase; 
      bool flag2 = !this.CanReloadFromUri; 
      if ((base2 == null) && flag2) 
      { 
       keepAlive = true; 
      } 
     } 
    } 
    return keepAlive; 
} 

Bây giờ bạn đã biết quy tắc. Đối tượng được lưu trong bộ nhớ nếu:

  • Nó không phải là đối tượng phụ thuộc;
  • Được đính kèm thích hợp JournalEntry.KeepAlive là đúng;
  • Nó không phải là một PageFunction và nó không thể được tải lại từ Uri.

Sau khi điều tra này có thể đáng đọc hơn về tài sản JournalEntry.KeepAlive trên MSDN.

Chiến lược này đã giúp tôi tìm thấy nhiều loại côn trùng liên quan đến bộ nhớ. Mong nó cũng giúp được cho bạn :).

PS: Nếu bạn tiếp tục gặp sự cố khi tìm thấy lỗ hổng cụ thể này, bạn có thể dán mẫu mã tối thiểu để chúng tôi sao chép và cung cấp cho bạn câu trả lời đúng hơn.

Chúc mừng, Anvaka

+0

Cảm ơn bạn đã giải thích chi tiết, nhưng tôi không chắc chắn tôi làm theo phần DependencyProperty. Nếu tôi đã đặt KeepAlive là sai trên mọi trang, tại sao nó vẫn được giữ trong bộ nhớ? – Brandon

+0

Thực hiện theo đường dẫn logic: ngay cả khi bạn đặt KeepAlive = false trên mỗi trang, bạn vẫn có thể nhận được true từ IsContentKeepAlive() khi flag2 là true, có nội dung:! CanReloadFromUri – Anvaka

+0

Ah, right. Cảm ơn câu trả lời tuyệt vời. – Brandon

5

tôi đã cùng một vấn đề và bảng xếp hạng cùng với phân tích bộ nhớ Ants. Ứng dụng này sử dụng một NavigationWindow để lưu trữ một số WPF Pages và điều hướng đã được thực hiện với codebehind này:

NavigationService.Navigate(new Page1()); 

Vấn đề được tạo ra bởi nhiều trang lưu giữ trong bộ nhớ bằng cách trên tạp chí và không thể được thu gom rác thải.

Điều tôi đã làm là thay thế NavigationWindow bằng cửa sổ bình thường, Trang có UserControls và điều khiển người dùng trao đổi bên trong cửa sổ, giống như trang. Có nhiều ví dụ về cách thực hiện việc này trong google. Sau khi xóa tất cả các cuộc gọi NavigationService.Navigate, cuối cùng tôi có thể thu thập tất cả các trang đã đóng bằng trình thu thập bộ nhớ kiến.

+1

Thông minh. Nhưng rất nhiều công việc. Ngoài ra, bạn sẽ không phải phát triển dịch vụ điều hướng của riêng mình? Tôi đã thử làm điều đó, và đó là một nỗi đau thực sự. – ouflak

+0

Đúng, nó đang xây dựng dịch vụ điều hướng riêng. Tuy nhiên, nó là cần thiết do rò rỉ bộ nhớ khi bạn thực hiện điều hướng '! This.CanReloadFromUri' tức là như' Navigate (new Page()); '. – xmedeko

Các vấn đề liên quan