我正在写一个VSTO,它循环浏览所有的幻灯片,浏览所有的形状,并将标题设置为一个值.我意识到,每次运行后,内存消耗都会增加.因此,我最小化我的代码,让它运行100次,最终每100次运行分配约20MB内存。
我的代码是由一个侧栏按钮执行的,演示文稿有大约30个幻灯片的标题,我的代码看起来像这样的按钮。
private void button1_Click(object sender, EventArgs e)
{
SetTitle_Direct();
Stopwatch watch = new Stopwatch();
watch.Start();
SetTitle_Direct();
watch.Stop();
//MessageBox.Show("Time spend: " + watch.Elapsed);
AMRefreshProgress.Maximum = 100;
AMRefreshProgress.Step = 1;
AMRefreshProgress.UseWaitCursor = true;
AMRefreshProgress.ForeColor = System.Drawing.ColorTranslator.FromHtml(ThisAddIn.amColor);
for (int i = 1; i <= 100; i++)
{
SetTitle_Direct();
AMRefreshProgress.PerformStep();
}
AMRefreshProgress.Value = 0;
AMRefreshProgress.UseWaitCursor = false;
Stopwatch watch2 = new Stopwatch();
watch2.Start();
SetTitle_Direct();
watch2.Stop();
MessageBox.Show("Time 1st run: " + watch.Elapsed + "\n Time 11th run: " + watch2.Elapsed);
}
SetTitle_Direct()循环播放幻灯片。
public void SetTitle_Direct()
{
PowerPoint.Presentation oPresentation = Globals.ThisAddIn.Application.ActivePresentation;
foreach (PowerPoint.Slide oSlide in oPresentation.Slides)
{
if (oSlide.Shapes.HasTitle == OFFICECORE.MsoTriState.msoTrue)
{
oSlide.Shapes.Title.TextFrame.TextRange.Text = "Test Main Title";
}
for (int iShape = 1; iShape <= oSlide.Shapes.Count; iShape++)
{
if (oSlide.Shapes[iShape].Type == Microsoft.Office.Core.MsoShapeType.msoPlaceholder)
{
if (oSlide.Shapes[iShape].PlaceholderFormat.Type == PowerPoint.PpPlaceholderType.ppPlaceholderSubtitle)
{
oSlide.Shapes[iShape].TextFrame.TextRange.Text = "Test Sub Title";
}
}
}
}
}
是什么原因导致AddIn分配越来越多的内存--或者如何避免这种情况?
当你开发一个基于VSTO的插件时,你通常会处理COM对象(PowerPoint是一个COM服务器)。随着每个返回COM对象的属性或方法调用,通常会增加一个对象引用,这导致在内存中保留对象,直到引用计数器减少并等于零。所以,我建议使用 Marshal.ReleaseComObject 方法来减少一个对象引用,让运行时保留内存并缩短对象的寿命。
为了能够释放每一个COM对象,你必须分割长长的属性和方法调用行。在单独的一行代码上声明每个属性或方法调用。这样一来,你就能够释放每一个对象,并在周围发生任何奇怪的事情时有效地调试代码。
你可以看看 什么时候在用.NET开发的Office插件中发布COM对象? 文章中获取更多信息。
另一种方法是使用垃圾收集器。
GC.Collect
GC.WaitForPendingFinalizers
GC.Collect
GC.WaitForPendingFinalizers