تصدير مع MEF في caliburn.micro - زيادة مشكلة الذاكرة
-
25-09-2019 - |
سؤال
لدي مشكلة في زيادة الذاكرة. يمكنني استخدام MEF في Caliburn.micro على إنشاء شاشة جديدة - WPF.
عرض نموذج الشاشة/العرض يبدو هكذا:
[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();
}
}
يمكنني استخدام فئة 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());
}
}
ومشكلتي هي:
- أدعو Opnechatscreen طريقة من الدردشة
- أضف مرجعًا على هذه النافذة إلى القاموس.
- عندما أغلق نافذة أسميها removechatscreen.
في removechascreen:
- أحصل على إجمالي الذاكرة ، على سبيل المثال ، هو 37000 ألف
- ثم أسمي طريقة dipose على orportlifetimecontext chatscreen
- قوة GC
- واحصل على إجمالي الذاكرة ، على سبيل المثال هو 39000K
استخدام الذاكرة يتزايد. آمل أن أتصل بـ Dispose Method على الكائن chatviewmodel وأيضًا كائن chatview يتم تدمير هؤلاء الكائن.
المحلول
لا تجبر 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 ، وعادة ما يتم ذلك في طريقة Dispose () للفئة التي يمكن التخلص منها. يجب تعريف كائن ChatView المشتق الخاص بك شيء مثل:
class ChatView : IChatViewModel, IDisposable
{ }
يتطلب ChatView طريقة Dispose () يتم تنفيذها. هناك نمط لمتابعة (من 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);
}
}