Tôi đã gặp sự cố tương tự khi sử dụng nhiều WPF DataGrid
cùng một lúc. Nó cuối cùng đã xuống đến hai vấn đề chính:
Resource Từ điển
Những có thể tắc nghẽn lớn nếu bạn sử dụng cơ bản WPF tính năng mà không bị cẩn thận.
Trong trường hợp của tôi, đối với một cuộn logic duy nhất trong ItemsControl
được chứa DataGrids
của tôi, tôi đã nhận được một cái gì đó giống như 10 triệu gọi để GetValue
và GetValueWithoutLock
trên ResourceDictionary. Hơn 1 giây để xử lý.
này số chính của ResourceDictionary
truy cập được gây ra bởi các nguồn khác nhau:
- động thu hồi tài nguyên: Nếu bạn có
ControlTemplates
, và tổng quát hơn các nguồn lực được đặt trong một số từ điển tài nguyên, và bạn truy cập chúng qua {DynamicResource ...}
, loại bỏ chúng . Có một số tĩnh một nơi nào đó và acces chúng trực tiếp.
- Tìm nạp kiểu: Nếu bạn không có kiểu dáng trên Hình ảnh khác nhau bạn sử dụng hoặc nếu bạn có Kiểu nhưng không đặt thuộc tính FrameworkElement.OverridesDefaultStyle, WPF sẽ cố gắng tìm kiểu phù hợp với kiểm soát trong tất cả các tài nguyên, kết quả trong rất nhiều quyền truy cập vào từ điển tài nguyên. Để tránh điều đó, hãy nhớ ghi đè tất cả các mẫu điều khiển của các điều khiển của bạn và đặt
Style={x:Null}
trên mỗi và mọi điều khiển (nếu bạn cần một kiểu cho điều khiển, đặt nó trong điều khiển của bạn và thêm OverridesDefaultStyle = true
)
- Ngụ ý DataTemplates: Mẫu dữ liệu ngầm định rất hữu ích nhưng không có gì nhiều. Khi tìm kiếm
DataTemplate
để áp dụng, WPF sẽ lại một lần nữa duyệt từ điển tài nguyên của bạn để tìm một số DataTemplate
phù hợp với các loại Chế độ xem của bạn. Giải pháp là sử dụng bộ chọn DataTemplate
cho mỗi và mọi điều khiển được liên kết với một ViewModel và triển khai cách tối ưu hóa để truy xuất đúng DataTemplate
. (Cá nhân tôi có một số lĩnh vực tĩnh cho dataTemplate của tôi mà tôi lấy chỉ một lần từ một resourceDictionary, và một tối ưu hóa DataTemplateSelector
trả về chúng khi cần thiết.)
Bindings
Bindings rất hữu ích, nhưng rất tốn kém, bộ nhớ khôn ngoan và hiệu suất khôn ngoan. Trong một môi trường rất hợp lý - từ một quan điểm thực hiện - bạn không thể chỉ sử dụng chúng mà không cần phải cẩn thận. Ví dụ, ràng buộc có thể tạo tối đa 3 WeakReferences cho mỗi đối tượng liên kết, có thể sử dụng sự phản chiếu, vv Cuối cùng tôi đã gỡ bỏ gần như tất cả các trình xử lý sự kiện ràng buộc và cắm vào sự kiện PropertyChexted của DataContext. Khi DataContext
thay đổi trên Điều khiển của tôi (bạn có sự kiện DataContextChanged
) Tôi kiểm tra xem DataContext
có hỗ trợ INotifyPropertyChanged
hay không và trong trường hợp đó, tôi đính kèm một trình xử lý sự kiện trên PropertyChanged
sự kiện và cập nhật các thuộc tính nếu cần. (Tôi chỉ có một cách ràng buộc, vì vậy đây là lý do tại sao tôi đã chọn cách làm việc này, nhưng có những giải pháp khác).
Điều này có vẻ khó chịu khi không sử dụng các ràng buộc khi sử dụng MVVM và WPF, nhưng thực sự không có cách nào để tối ưu hóa các ràng buộc trong trường hợp của tôi.
Điều cuối cùng: nếu bạn có Freezable
đối tượng (chẳng hạn như Brushes chẳng hạn), đừng ngần ngại Freeze
nếu bạn có thể.
Đó là một số lời khuyên có thể giúp bạn tối ưu hóa mã của mình. Bạn sẽ cần một profiler (Tôi luôn luôn khuyên dùng dotTrace vì đây là profiler tốt nhất mà tôi từng sử dụng) để theo dõi những gì đang thực sự xảy ra và điều chỉnh theo kết quả của bạn.
Chúc may mắn!
Cảm ơn câu trả lời chi tiết của bạn. Nó đã chứa một số điểm tôi có thể cải thiện trong ứng dụng của tôi (freezables, ghi đè kiểu mặc định). Tôi sẽ kiểm tra điều này và báo cáo sau. –
Chắc chắn, hãy cho tôi biết cách thức hoạt động! Nó thực sự là một bài tập tốt cho tôi khi tôi phải viết một bài đăng trên blog của tôi :) – Sisyphe
Chúng tôi có rất nhiều từ điển tài nguyên cho mọi thứ và ứng dụng vẫn rất nhanh.Cách chúng ta tiếp cận nó là tạo một từ điển tài nguyên cho một tài nguyên (như kiểu, vectơ, cọ vẽ, vv), sau đó từ mỗi khung nhìn, chúng ta chỉ tham khảo các từ điển tài nguyên cần thiết. Vấn đề là bản thân lưới đồng nhất, bởi vì nó không ảo hóa. – adminSoftDK