Exporter avec MEF Caliburn.Micro - L'augmentation de problème de mémoire
-
25-09-2019 - |
Question
J'ai un problème de plus en plus la mémoire. J'utilise MEF caliburn.micro sur la création nouvel écran -. Fenêtre WPF
voir le modèle de look écran / vue comme ceci:
[Export(typeof(IChatViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChatViewModel : Screen, IChatViewModel
{}
Lors de la création que j'utilise usine à exporter, est ici controleur:
public interface IViewModelsControler
{
ExportLifetimeContext<IChatViewModel> CreatChatViewModel();
}
[Export(typeof(IViewModelsControler))]
public class ViewModelsControler : IViewModelsControler
{
[Import]
public ExportFactory<IChatViewModel> ChatViewFactory { get; set; }
public ExportLifetimeContext<IChatViewModel> CreatChatViewModel()
{
return ChatViewFactory.CreateExport();
}
}
J'utilise la classe ViewModelsControler en classe ChatScreenManager. Cette classe Ouvrir / écran Supprimer le chat.
est-il ici:
[Export(typeof(IChatScreenManager))]
public class ChatScreenManager : IChatScreenManager
{
private IWindowManager _windowManager;
[Import]
public IViewModelsControler ViewModelControler { get; set; }
[ImportingConstructor]
public ChatScreenManager(IWindowManager windowManager)
{
_windowManager = windowManager;
ActiveChatScreens = new Dictionary<string, ExportLifetimeContext<IChatViewModel>>();
}
//store active screen
public Dictionary<string, ExportLifetimeContext<IChatViewModel>> ActiveChatScreens { get; set; }
public void OpenChatScreen(DetailData oponent, string avatarNick, BitmapImage avatarImage)
{
if (!ActiveChatScreens.ContainsKey(oponent.Info.Nick))
{
//create new chat screen with view model controler
ExportLifetimeContext<IChatViewModel> chatScreen = ViewModelControler.CreatChatViewModel();
//show
_windowManager.Show(chatScreen.Value);
//add ref to the dic
ActiveChatScreens.Add(oponent.Info.Nick, chatScreen);
}
}
public void RemoveChatScreen(string clossingScreen)
{
MessageBox.Show(GC.GetTotalMemory(true).ToString());
ActiveChatScreens[clossingScreen].Dispose();
ActiveChatScreens.Remove(clossingScreen);
GC.Collect();
GC.SuppressFinalize(this);
MessageBox.Show(GC.GetTotalMemory(true).ToString());
}
}
Et mon problème est:
- Je l'appelle méthode OpneChatScreen de ChatScreenManager il ouvre une nouvelle fenêtre WPF
- Ajouter une référence dans cette fenêtre dans le dictionnaire.
- Quand je suis fermeture de la fenêtre que j'appelle RemoveChatScreen.
En RemoveChaScreen:
- Je reçois la mémoire totale, par exemple est-il 37,000K
- Alors je l'appelle méthode dipose sur ExportLifetimeContext chatScreen
- Force GC
- Et obtenir de la mémoire totale, par exemple est-il 39,000K
Utilisation de la mémoire augmente Stil. J'espère que si je l'appelle Éliminez méthode sur ChatViewModel objet et également ChatView objet ces objets sont détruits.
La solution
Ne pas forcer GC! En outre, la méthode Dispose()
doit suivre le retrait de votre collection.
public void RemoveChatScreen(string closingScreen)
{
MessageBox.Show(GC.GetTotalMemory(true).ToString());
IChatViewModel chatWindow = ActiveChatScreens[closingScreen]
// remove from collection - GC may pass over object referenced in collection
// until next pass, or 3rd pass...who knows, it's indeterminate
ActiveChatScreens.Remove(closingScreen);
// all clean up should be performed within Dispose method
chatWindow.Dispose();
//GC.Collect();
//GC.SuppressFinalize(this);
MessageBox.Show(GC.GetTotalMemory(true).ToString());
}
Obliger la collecte des ordures n'est pas recommandé. Il y a plusieurs façons de travailler avec GC, cependant, et qui est généralement fait dans la méthode Dispose () de la classe à usage unique. Votre objet dérivé ChatView doit être défini quelque chose comme:
class ChatView : IChatViewModel, IDisposable
{ }
ChatView nécessite une méthode Dispose () être mis en œuvre. Il y a un modèle à suivre < em> (de MSDN) lors de la création de classes à usage unique:
// Design pattern for a base class.
public class ChatView : IChatViewModel, IDisposable
{
private bool disposed = false;
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
disposed = true;
}
}
// Use C# destructor syntax for finalization code.
~ChatView()
{
// Simply call Dispose(false).
Dispose (false);
}
}