У меня есть эта проблема.Я разрабатываю приложение WPF с архитектурой MVVM.В качестве фреймворка MVVM я использую Caliburn.Micro, а при внедрении сервиса я использую MEF.
В классе модели представления я использую таймер Dispatcher, который вызывает каждые 3 секунды метод обслуживания.Этот сервисный метод отправляет POST-запрос на сервер и анализирует HTML-ответ / десериализует строку JSON с JSON.NET.
Этот метод возвращает наблюдаемый словарь, это тип: string, Friend.
Класс Friend состоит только из строковых свойств и одного изображения в виде типа BitmapImage.
ЗдесьСервисный метод:
public MyObservableDictionary<string, Friend> LoadFriends(Account account)
{
var friends = new MyObservableDictionary<string, Friend>();
var sortedFriends = new MyObservableDictionary<string, Friend>();
const string allData = "&allData=1";
var htmlStringResult = new StringBuilder();
htmlStringResult = "GET HTML RESPOSE"
if (htmlStringResult.Length > 3 && htmlStringResult.ToString() != "false")
{
try
{
var jsonString = new StringBuilder();
jsonString.Append(htmlStringResult.Replace(@"s_", "m_"));
var friendsAsStringArray = JsonConvert.DeserializeObject<MyObservableDictionary<string, string[]>>(jsonString.ToString());
foreach (var friend in friendsAsStringArray)
{
var item = new KeyValuePair<string, Friend>(friend.Key, new Friend
{
IdUser = friend.Value[0],
Nick = friend.Value[1],
SefNick = friend.Value[1],
Status = int.Parse(friend.Value[2]),
Photo = friend.Value[3],
Sex = int.Parse(friend.Value[4]),
IsFriend = Convert.ToBoolean(int.Parse(friend.Value[5]) * -1)
});
friends.Add(item);
}
//sort item in dictionary A-Z
var query = friends.OrderByDescending(f => f.Value.Status).ThenBy(f => f.Value.Nick);
foreach (var keyValuePair in query)
{
sortedFriends.Add(keyValuePair.Key, keyValuePair.Value);
}
//CLEAN OLD DATA
friends.Clear();
}
catch (Exception exception)
{
throw exception;
}
return sortedFriends;
}
return new MyObservableDictionary<string, Friend>();
}
В представлении модели класса я привязываю наблюдаемый словарь к списку.В этом классе я вызываю таймер каждые 3 секунды. Сервисный метод LoadFriend .
Я возвращаю свежие данные в наблюдаемый словарь, и этими данными я обновляю словарь, который связывается со списком.
Вот вид модели класса:
[Export(typeof(IMessengerViewModel))]
public class MessengerViewModel : Screen, IViewModelIdentity,
IMessengerViewModel, IHandle<Rp>, IHandle<string>
{
private IPokecService _service;
private MyObservableDictionary<string, Friend> _friends;
private MyObservableDictionary<string, Friend> _freshFriends;
private DispatcherTimer _dispatcherTimer;
[ImportingConstructor]
public MessengerViewModel(IPokecService service)
{
_service = service;
_dispatcherTimer = new DispatcherTimer();
_dispatcherTimer.Tick += DispatcherTimer_Tick;
_dispatcherTimer.Interval = TimeSpan.FromSeconds(3);
_dispatcherTimer.Start();
}
#region Timer
/// <summary>
/// Refresh contact list, check for new messages
/// </summary>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
private void DispatcherTimer_Tick(object sender, EventArgs eventArgs)
{
//retrieve new data from server
_freshFriends = _service.LoadFriends(Account);
_friends.Clear();
//refresh dictionary
foreach (var freshFriend in _freshFriends)
{
_friends.Add(freshFriend);
}
}
#endregion
}
Я делаю простой тест:
- запуск приложения с таймером
- запуск приложениябез таймера
- с таймером, но пустой логикой для метода timer_tick
Я проверяю значения в диспетчере задач и в профилировщике памяти ANTS, вот значения:
Процесс диспетчера задач:
- Приложение с таймером
- после запуска: 40 133 К
- через 5 минут: 70 261 К
- через 10 минут: 74 288 К
- Приложение без таймера
- после запуска: 37 488 К
- через 5 минут: 37 412 К
- через 10 минут: 37 760 К
- Приложение с таймером, но с пустой логикой
- после запуска: 37 474 К
- через 5 минут: 37,340K
- через 10 минут: 37,476k
ANTS Профилировщик памяти - Частные байты
- Приложение с таймером
- после запуска: 73,132 МБ
- через 5 минут: 97,72 МБ
- через 10 минут: 100,12 МБ
- Приложение без таймера
- после запуска: 67,24 МБ
- через 5 минут: 66,21 МБ
- через 10 минут: 66,21 МБ
- Приложение с таймером, но с пустой логикой
- после запуска: 67,3 МБ
- через 5 минут: 66,32MB
- через 10 минут: 66,41MB
Я не знаю, что это нормальные значения.Возможно, у меня утечка памяти в приложении.
Моей первой идеей была проверка изображений в классе Friend, но изображение сохраняется в классе BitmapImage.Этот класс не реализует интерфейс IDisposable, поэтому я не могу вызвать метод Dispose для старых элементов в словаре.
Максимальное количество приватных байтов составило 124,12 МБ. Я думаю, этого вполне достаточно.
Я никогда не обращался с использованием памяти в .NET, я не знаю, что может быть не так.
Спасибо за помощь, если кто-то объяснит мне эту проблему, я буду очень ему признателен.
Я думаю, что позвоните в мой таймер сборщик мусора, но я думаю, что это идея goog.
Размер одного изображения составляет 5-10 КБ.И в словаре около 20-30 наименований.
Я загружаю изображение из Интернета, изображение - это URL.
public BitmapImage ProfilePhoto ...{ get; set; }
private BitmapImage CreateProfilePhoto()
{
var img = new BitmapImage();
img.BeginInit();
img.UriSource = Photo == "0" ? DefaultPhoto.GetDefaultPhoto(Sex) : new Uri(PhotoURL, UriKind.Absolute);
img.EndInit();
return img;
}
....
ProfilePhoto = CreateProfilePhoto();