我有这个问题。我用MVVM架构开发WPF应用程序。作为MVVM框架,我使用Caliburn.Micro并在服务注入时使用MEF。
在视图模型类中,我使用Dispatcher Timer,它调用每3秒的服务方法。此服务方法在服务器上发送POST请求,并使用JSON.NET解析HTML响应/反序列化JSON字符串。
此方法返回可观察字典,类型为: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
}
我做了一个简单的测试:
我检查任务管理器和ANTS内存分析器中的值,这里是值:
任务管理器流程:
ANTS内存探查器 - 私有字节
我不知道这个值是正常的。也许我在app中有内存泄漏。
我的第一个想法是在Friend类中检查图像,但是图像存储在BitmapImage类中。这个类没有实现接口IDisposable,所以我不能在字典中的旧项目上调用Dispose方法。
最大私有字节数为124,12 MB我觉得它已经足够了。
我从不处理.NET中的内存使用情况,我不知道会出现什么问题。
感谢您的帮助,如果有人向我解释这个问题,我将非常感激他/她。
我想在我的计时器垃圾收集器中调用,但我认为这是goog的想法。
一张图像的尺寸为5-10kB。在词典中约有20-30项。
我从网上下载图片,图片uri是网址。
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();
答案 0 :(得分:1)
这非常宝贵:Finding Memory Leaks in WPF-Based Applications。
BitmapImage
存在问题。
答案 1 :(得分:1)
我在片段中看到的显而易见的事情是你最终会保留2个词典。
_friends中有一个,_freshfriends中有一个。
根据字典的大小,这可以解释一些不同之处。作为第一步,是否有任何理由为_freshFriends不是方法局部变量?