Worksheet.Name导致OutOfMemoryException异常
问题描述:
.NET4 C#VSTO4 Excel插件:
下面的函数被调用很多时候,我们说每一秒钟:Worksheet.Name导致OutOfMemoryException异常
/// <summary>
/// Gets a unique identifier string of for the worksheet in the format [WorkbookName]WorksheetName
/// </summary>
/// <param name="workbook">The workbook.</param>
/// <param name="worksheet">The worksheet.</param>
/// <returns>
/// A unique worksheet identifier string, or an empty string.
/// </returns>
public static string GetWorksheetUniqueIdentifier(Workbook workbook, dynamic worksheet)
{
if (workbook == null) return string.Empty;
if (worksheet == null) return string.Empty;//Note: Worksheet can also be a diagram!
return string.Format("[{0}]{1}", workbook.Name, worksheet.Name);
}
一段时间后,我得到了以下情况除外:
System.OutOfMemoryException
at System.Collections.Generic.Dictionary`2.Resize()
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at Microsoft.CSharp.RuntimeBinder.Semantics.SYMTBL.InsertChildNoGrow(Symbol child)
at Microsoft.CSharp.RuntimeBinder.Semantics.SymFactoryBase.newBasicSym(SYMKIND kind, Name name, ParentSymbol parent)
at Microsoft.CSharp.RuntimeBinder.Semantics.SymFactory.CreateLocalVar(Name name, ParentSymbol parent, CType type)
at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.PopulateLocalScope(DynamicMetaObjectBinder payload, Scope pScope, ArgumentObject[] arguments, IEnumerable`1 parameterExpressions, Dictionary`2 dictionary)
at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.BindCore(DynamicMetaObjectBinder payload, IEnumerable`1 parameters, DynamicMetaObject[] args, DynamicMetaObject& deferredBinding)
at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.Bind(DynamicMetaObjectBinder payload, IEnumerable`1 parameters, DynamicMetaObject[] args, DynamicMetaObject& deferredBinding)
at Microsoft.CSharp.RuntimeBinder.BinderHelper.Bind(DynamicMetaObjectBinder action, RuntimeBinder binder, IEnumerable`1 args, IEnumerable`1 arginfos, DynamicMetaObject onBindingError)
at Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder.FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
at System.Dynamic.DynamicMetaObject.BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
at System.Dynamic.InvokeMemberBinder.Bind(DynamicMetaObject target, DynamicMetaObject[] args)
at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
at CallSite.Target(Closure , CallSite , Object , Object)
at TestAddIn.ExcelAccessor.GetWorksheetUniqueIdentifier(Workbook workbook, Object worksheet)
at TestAddIn.ExcelAccessor.GetCurrentWorksheetUniqueIdentifier()
at TestAddIn.ExcelAccessor.timerExcelObserver_Tick(Object sender, EventArgs e)--------------------------------------------------------------------------------------------------------
长途区号:
private static Timer timerExcelObserver = new Timer();
...
timerExcelObserver.Tick += new EventHandler(this.timerExcelObserver_Tick);
timerExcelObserver.Interval = 1000;
timerExcelObserver.Start();
...
private void timerExcelObserver_Tick(object sender, EventArgs e)
{
...
var updatedWorksheetIdentifierString = GetCurrentWorksheetUniqueIdentifier();
...
}
public static string GetCurrentWorksheetUniqueIdentifier()
{
return GetWorksheetUniqueIdentifier(ExcelApplication.ActiveWorkbook, ExcelApplication.ActiveSheet);
}
我不知道为什么我收到一个异常!
这可能有助于在GetWorksheetUniqueIdentifier中使用“使用”吗?
using(worksheet)
{
return string.Format("[{0}]{1}", workbook.Name, worksheet.Name);
}
有没有人有答案?
答
尝试明确释放COM对象:
public static string GetCurrentWorksheetUniqueIdentifier()
{
var workbook = ExcelApplication.ActiveWorkbook;
var worksheet = ExcelApplication.ActiveSheet;
try
{
return GetWorksheetUniqueIdentifier(workbook, worksheet);
}
finally
{
if (workbook != null &&
Marshal.IsComObject(workbook))
Marshal.ReleaseComObject(workbook);
if (worksheet != null &&
Marshal.IsComObject(worksheet))
Marshal.ReleaseComObject(worksheet);
}
}
这已经知道,修复一些与Office相关的情景记忆的问题。
+0
**我不知道这是否真正解决了这个问题,因为我无法复制它。但这是迄今为止最好的答案。** – jreichert
看起来好像在某些字典中插入时出错了,你可以分享完整的堆栈跟踪 –
这个代码被调用的地方在哪里,或者它是如何被使用的?它似乎不是问题的直接原因(它在一个Dictionary resize方法内死亡),所以调用代码可能有问题。 –
不要处理'worksheet'对象,这是如果使用您发布的'using'语句会发生的情况。调用方很可能在您的方法结束后仍然需要引用'工作表'。 – Keith