所以,我正在使用C#和WPF构建Office(通过VSTO)的应用程序。我发现在启动后永远不会收集WPF应用程序(通过内存分析器)。
我要为WPF应用程序创建一个新的AppDomain,在AppDomain中启动它,然后使用,卸载AppDomain,但我仍然有对象 - 我的句柄仍在增加
有谁知道VSTO和WPF应用程序的任何奇怪行为?我唯一的猜测是,由于某种原因,WPF应用程序加载在Office共享的UI线程上,所以它永远不会被清理......
对增加手柄的任何想法?我从客户的部署团队那里得到了很多反对意见,即“增加的句柄是不可接受的。”
编辑:
让我说清楚 - WPF应用程序是从功能区启动的,然后它们在相应的应用程序中生成输出,即如果在Excel中,您将输入信息,然后它将基于您为您构建电子表格提供的信息;如果在PowerPoint中,您将输入信息(在功能区中启动的WPF应用程序中),它将根据您提供的信息构建幻灯片。
答案 0 :(得分:1)
我的理解是VSTO解决方案(至少从Visual Studio 2010开始)总是使用default COM shim将VSTO加载项加载到单独的AppDomain。这种隔离可以保护您的加载项免受其他加载项的任何不稳定性的影响。
由于在与VSTO主机应用程序(例如Excel)交互时创建的隐藏运行时可调用包装(RCW),您的应用程序的内存使用量可能会增长?
我的第一个VSTO应用程序最初依靠Marshal.ReleaseComObject()
来释放RCW,但是,我根据这些博客文章改变了我在下面使用的方法:
我现在使用这种方法强制GC
public static class OfficeHelper
{
/// <summary>
/// Forces a GC to release unused run time callable wrappers around COM objects
/// </summary>
/// <example>
/// dynamic rcw;
/// try
/// {
/// rcw = Globals.ThisWorkbook.ActiveSheet;
/// // do something
/// // ...
/// }
/// finally
/// {
/// rcw = null;
/// OfficeHelper.Cleanup();
/// }
/// </example>
public static void Cleanup()
{
System.Diagnostics.Debug.Print("OfficeHelper::Cleanup - GC forced");
GC.Collect();
GC.WaitForPendingFinalizers();
System.Diagnostics.Debug.Print("OfficeHelper::Cleanup - GC finished");
}
}
到目前为止,这种方法在我的应用程序中运行良好,GC时间比我预期的要快。