2012-05-30 17 views
7

.Net4 C# VSTO4 Excel Add-in:

La seguente funzione viene chiamata molto spesso, diciamo ogni secondo: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); 
    } 

Dopo un po ', io sono sempre il seguente eccezione:

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

prefisso telefonico è:

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

ho idea perché sto ottenendo un'eccezione!

Può forse aiutare a prendere una "utilizzando" in GetWorksheetUniqueIdentifier?

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

Qualcuno ha una risposta?

+1

sembra che qualcosa vada storto quando si inserisce in un dizionario, puoi condividere lo stacktrace completo –

+2

Da dove viene chiamato questo codice o come viene utilizzato? Non sembra essere la causa diretta del problema (che sta morendo all'interno di un metodo di ridimensionamento del dizionario), quindi il codice chiamante potrebbe avere il problema. –

+0

Non disporre l'oggetto 'worksheet', che sarebbe ciò che accadrebbe se si usasse l'istruzione' using' che hai postato. È probabile che il chiamante debba ancora fare riferimento a 'worksheet' dopo che il metodo è terminato. – Keith

risposta

0

Provare a rilasciare gli oggetti COM in modo esplicito:

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

Questo è stato conosciuto per risolvere i problemi di memoria in alcuni scenari di Office-related.

+0

** Non so se questo risolve veramente il problema, perché non riesco a riprodurlo. Ma è la migliore risposta finora. ** – jreichert

Problemi correlati