2012-05-30 11 views
7

.Net4 C# VSTO4 Excel Add-in:

La siguiente función se llama con frecuencia, digamos que cada segundo:Worksheet.Name provoca 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); 
    } 

Después de un tiempo, yo estoy recibiendo el siguiente excepción:

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)-------------------------------------------------------------------------------------------------------- 

código de llamada es:

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); 
    } 

no tengo ni idea de por qué me estoy haciendo una excepción!

¿Puede ser útil tomar un "uso" en GetWorksheetUniqueIdentifier?

using(worksheet) 
{ 
    return string.Format("[{0}]{1}", workbook.Name, worksheet.Name); 
} 

¿Alguien tiene una respuesta?

+1

parece que algo va mal al insertar en algún diccionario, ¿puedes compartir stacktrace completo –

+2

¿De dónde se está llamando este código o cómo se está utilizando? No parece ser la causa directa del problema (que está muriendo dentro de un método de cambio de tamaño del diccionario), por lo que el código de llamada puede tener el problema. –

+0

No deseche el objeto 'worksheet', que es lo que pasaría si usa la instrucción' using' que publicó. Es probable que la persona que llama aún necesite hacer referencia a la "hoja de trabajo" después de que termine su método. – Keith

Respuesta

0

tratar de dejar los objetos COM explícitamente:

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); 
    } 
} 

Esto se ha sabido para solucionar los problemas de memoria en algunos escenarios relacionados a la oficina.

+0

** No sé si esto realmente soluciona el problema, porque no puedo reproducirlo. Pero es la mejor respuesta hasta ahora. ** – jreichert

Cuestiones relacionadas