Tôi đang làm việc với số lượng lớn các đối tượng (POI) đang được hiển thị trên MapControl
. Tôi đang giúp bản thân mình với một MVVM Light để tuân theo các quy tắc của phương pháp MVVM.Windows Phone 8.1 Rò rỉ bộ nhớ WinRT với ObservableCollection
Vì tôi có nghĩa vụ hiển thị mọi đối tượng trên bản đồ, tôi phải sử dụng bộ sưu tập MapItemsControl
chứ không phải MapElements
. Bộ sưu tập này liên kết với đối tượng ObservableCollection<PushpinViewModel>
(Pushpins
) trong tương ứng ViewModel
. Mọi thứ hoạt động như mong đợi, đến mức tối đa, khi tôi muốn làm mới Pushpins
. Vấn đề là rò rỉ bộ nhớ. Nhưng trước tiên, một số mã để hình dung vấn đề:
XAML:
<maps:MapControl x:Name="Map"
x:Uid="MapControl">
<maps:MapItemsControl ItemsSource="{Binding Pushpins}">
<maps:MapItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Image}"/>
</DataTemplate>
</maps:MapItemsControl.ItemTemplate>
</maps:MapItemsControl>
MainViewModel:
public class MainViewModel : ViewModelBase
{
public RelayCommand AddCommand { get; set; }
public RelayCommand ClearCommand { get; set; }
public RelayCommand CollectCommand { get; set; }
public ObservableCollection<PushpinViewModel> Pushpins { get; set; }
/* Ctor, initialization of Pushpins and stuff like that */
private void Collect()
{
GC.Collect(2);
GC.WaitForPendingFinalizers();
GC.Collect(2);
PrintCurrentMemory();
}
private void Clear()
{
Pushpins.Clear();
PrintCurrentMemory();
}
private void Add()
{
for (int i = 0; i < 1000; i++)
{
Pushpins.Add(new PushpinViewModel());
}
PrintCurrentMemory();
}
private void PrintCurrentMemory()
{
Logger.Log(String.Format("Total Memory: {0}", GC.GetTotalMemory(true)/1024.0));
}
}
PushpinViewModel:
public class PushpinViewModel: ViewModelBase
{
public string Image { get { return "/Assets/SomeImage.png"; } }
~PushpinViewModel()
{
Logger.Log("This finalizer never gets called!");
}
}
Bây giờ, hãy xem xét các tình huống sau. Tôi thêm vào bộ sưu tập yếu tố. Chúng được trả lại, bộ nhớ được phân bổ, mọi thứ đều ổn. Bây giờ tôi muốn xóa bộ sưu tập và thêm một bộ sưu tập khác (khác trong kịch bản thực) 1000 phần tử. Vì vậy, tôi gọi phương thức Clear()
. Nhưng không có gì xảy ra! Pushpins
bị xóa, nhưng PushpinViewModel
của finalizers không được gọi! Sau đó, tôi thêm 1000 phần tử một lần nữa và việc sử dụng bộ nhớ của tôi tăng gấp đôi. Bạn có thể đoán điều gì sẽ xảy ra tiếp theo. Khi tôi lặp lại quy trình này Clear()
- Add()
3-5 lần ứng dụng của tôi gặp sự cố.
Vì vậy, vấn đề là gì? Rõ ràng ObservableCollection
đang giữ tham chiếu đến các đối tượng PushpinViewModel
sau Clear()
đã được thực hiện trên đó, do đó chúng không thể được thu thập rác. Tất nhiên buộc GC thực hiện thu gom rác thải không giúp (đôi khi thậm chí làm cho tình hình tồi tệ hơn).
Điều này khiến tôi bận tâm trong 2 ngày, tôi đã thử nhiều kịch bản khác nhau để thử và khắc phục vấn đề này, nhưng thành thật mà nói, không có gì hữu ích. Chỉ có một thứ không đáng giá - tôi không nhớ chính xác kịch bản, nhưng khi tôi đã giao Pushpins = null
, và sau đó đã làm điều gì đó hơn, VehiceViewModel
đã bị hủy. Nhưng điều đó không hiệu quả đối với tôi, bởi vì tôi cũng nhớ rằng tôi đã có vấn đề với việc hình dung các chân trên bản đồ sau Clear()
.
Bạn có bất kỳ ý tưởng nào có thể gây ra rò rỉ bộ nhớ này không? Làm thế nào tôi có thể buộc các thành viên của OC
phá hủy? Có thể có một số loại thay thế cho OC
? Cảm ơn bạn trước vì đã giúp đỡ!
EDIT:
tôi đã làm một số xét nghiệm với XAML bản đồ kiểm soát - https://xamlmapcontrol.codeplex.com/, và kết quả là đáng ngạc nhiên. Hiệu suất bản đồ tổng thể với> 1000 phần tử được thêm vào, kém hơn một số nguyên tố MapControl
, NHƯNG, nếu tôi gọi Add()
x1000, sau đó Clear()
, sau đó Add()
x1000, trình hoàn tất của PushpinViewModel
sẽ được gọi! Bộ nhớ được giải phóng và ứng dụng không bị lỗi. Vì vậy, chắc chắn có điều gì đó sai trái với số MapControl
của Microsoft ...
Vấn đề là khả năng các bitmap bạn đang tải về mẫu đang được lưu trữ trong bộ nhớ. Thu thập GC không xóa nó khỏi bộ nhớ cache. Xem [những] này (http://stackoverflow.com/questions/1684489/how-do-you-make-sure-wpf-releases-large-bitmapsource-from-memory) [liên quan] (http://stackoverflow.com/questions/5530645/release-bitmapimages-used-as-image-control-source-memory-problem) Các câu hỏi. –
Cảm ơn câu trả lời của bạn. Tôi đã điều tra khả năng này, và đồng ý rằng nó thực sự có thể là một lý do. Tôi đã kiểm tra các liên kết của bạn, câu trả lời đáng buồn được đăng có chủ yếu áp dụng cho các ứng dụng WPF (tôi đang trong một WinRT - Universal App). Tôi đã quản lý để tải một hình ảnh từ các dòng (như một phương pháp async, nhưng nó đã làm việc) - unfortunatelly nó đã không giúp đỡ. Tiêu thụ bộ nhớ thậm chí còn lớn hơn: ( – Malutek
Tôi không thể nói với vấn đề cụ thể của bạn, nhưng tôi đã có một số vấn đề với MapItemsControl. Tôi đã có khá nhiều thiết lập tương tự bạn đã làm - liên kết với ObservableCollection bằng MVVM. Tôi điều hướng ra khỏi bản đồ để xem khác, sau đó trở lại bản đồ, và lặp đi lặp lại điều này qua lại 3-5 lần, tôi sẽ (thường) nhận được một lỗi "Truy cập Vi phạm" mà tôi thu hẹp xuống MapItemsControl. với một hành vi mà có một nguồn mặt hàng và vẽ pushpins trên bản đồ cho tôi thay vào đó, hãy cho tôi biết nếu bạn muốn tôi đăng nguồn. –