Caliburn.Micro で MEF を使用してエクスポート - 増加するメモリ問題
-
25-09-2019 - |
質問
メモリの増設に問題があります。新しい画面の作成 - WPFウィンドウでcaliburn.microのMEFを使用します。
画面/ビューのビュー モデルは次のようになります。
[Export(typeof(IChatViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChatViewModel : Screen, IChatViewModel
{}
作成時に ExportFactory を使用します。コントローラーは次のとおりです。
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();
}
}
ChatScreenManagerクラスのViewModelsControlerクラスを使用します。このクラスはチャット画面を開く/削除します。
はい、これ:
[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());
}
}
そして私の問題は次のとおりです。
- ChatScreenManager から OpneChatScreen メソッドを呼び出して、新しい WPF ウィンドウを開きます
- このウィンドウの参照を辞書に追加します。
- ウィンドウを閉じるときに、RemoveChatScreen を呼び出します。
RemoveChaScreen で:
- 合計メモリを取得します。たとえば、37,000K です。
- 次に、ExportLifetimeContext chatScreen で Dipose メソッドを呼び出します
- 強制GC
- そして、合計メモリを取得します。たとえば、39,000K です。
メモリ使用量は依然として増加しています。ChatViewModel オブジェクトと ChatView オブジェクトの Dispose メソッドを呼び出すと、これらのオブジェクトが破棄されることを願っています。
解決
GCを強制しないでください!また、Dispose()
方法は、あなたのコレクションからの除去に従わなければならない。
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());
}
ガベージコレクションを強制することはお勧めしません。そこの仕事のやり方は、しかし、GCであり、そしてそれは、一般的に使い捨てクラスの処分()メソッドで行われます。あなたの派生ChatViewオブジェクトのようなものを定義する必要があります:
class ChatView : IChatViewModel, IDisposable
{ }
ChatViewは廃棄()メソッドを実装することを必要とします。 の<フォローするパターンがありますem>の使い捨てのクラスを作成するときにの(MSDNから):
// 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);
}
}
所属していません StackOverflow