2011-01-05 12 views
0

Ich habe Probleme mit der Speichererweiterung. Ich benutze MEF in caliburn.micro auf Erstellung neuer Bildschirm - WPF-Fenster.Exportieren mit MEF in Caliburn.Micro - Speicherproblem erhöhen

Ansicht Modell der Bildschirm/Ansicht wie folgt aussehen:

[Export(typeof(IChatViewModel))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class ChatViewModel : Screen, IChatViewModel 
    {} 

Auf Schöpfung ich ExportFactory verwenden, Controler ist hier:

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(); 
    } 
} 

I ViewModelsControler Klasse in ChatScreenManager Klasse. Diese Klasse öffnet/entfernt den Chat-Bildschirm.

Hier ist es:

[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()); 
     } 
    } 

Und mein Problem ist:

  • I OpneChatScreen Methode von ChatScreenManager nennen es neue WPF-Fenster öffnen
  • Referenz hinzufügen in diesem Fenster in das Wörterbuch.
  • Wenn ich Fenster schließe, rufe ich RemoveChatScreen.

In RemoveChaScreen:

  • I Gesamtspeicher zu erhalten, ist es beispielsweise 37.000
  • Dann dipose Methode auf ExportLifetimeContext chatScreen
  • Kraft GC
  • Und Gesamtspeicher bekommen ich rufe, zum Beispiel ist es 39,000K

Speicherverbrauch ist stil steigt Ing. Ich hoffe, wenn ich Dispose-Methode auf Objekt ChatViewModel und auch ChatView-Objekt aufrufen, werden diese Objekte zerstört.

+0

FYI, verwenden Sie die [C#] oder [net] Tags Ihre Fragen zu identifizieren, um Code-Beispiele richtig formatiert werden kann. ;) – IAbstract

Antwort

2

GC nicht erzwingen! Außerdem sollte die Methode Dispose() der Entfernung aus Ihrer Sammlung folgen.

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()); 
} 

Das Erzwingen der Speicherbereinigung wird nicht empfohlen. Es gibt jedoch Möglichkeiten, mit GC zu arbeiten, und dies geschieht in der Regel in der Dispose() -Methode der Disposable-Klasse. Ihr abgeleitetes ChatView-Objekt sollte wie folgt definiert werden:

class ChatView : IChatViewModel, IDisposable 
{ } 

ChatView erfordert eine Dispose() - Methode implementiert werden. Es gibt eine pattern to follow(von MSDN) wenn Einweg-Klassen erstellen:

// 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); 
    } 
} 
+0

Vielen Dank für den Rat, mein Problem ist jetzt, wie verbinden Dispose-Methode von ViewModel-Klasse mit "Ansicht Dispose-Methode" im WPF-Fenster (Ansicht ist WPF-Fenster). Zum Beispiel rufe ich die Dispose-Methode für die ViewModel-Klasse auf und sie ruft auch die Dipose-Methode für das View-WPF-Fensterobjekt auf. –

+0

Zum Beispiel rufe ich Dispose-Methode auf ViewModel und es ruft auch die Destroy-Ansicht auf, die WPF-Fenster ist. –

+0

Ich dachte, http://stackoverflow.com/questions/4597317/problem-with-mef-exportfactoryt-call-dispose-method/4599836#4599836 beantwortete es für Sie. – IAbstract