2012-05-30 16 views
7

.Net4 C# VSTO4 Excel Add-In:

Poniższa funkcja nazywa się bardzo często, powiedzmy co drugi:Worksheet.Name powoduje 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); 
    } 

po chwili otrzymuję następujący wyjątek:

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

Wywołanie kodu jest:

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

nie mam pojęcia, dlaczego jestem z dostaniem wyjątek!

Czy może pomóc w "użyciu" narzędzia GetWorksheetUniqueIdentifier?

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

Czy ktoś ma odpowiedź?

+1

wygląda tak, jakby coś poszło nie tak podczas wstawiania do jakiegoś słownika, czy możesz udostępnić pełną ścieżkę stosu –

+2

Skąd ten kod jest wywoływany lub jak jest używany? Nie wydaje się być bezpośrednią przyczyną problemu (który umiera w metodzie zmiany rozmiaru słownika), więc kod wywołujący może mieć problem. –

+0

Nie wolno wyrzucać obiektu 'worksheet', co by było, gdybyś użył wysłanego przez ciebie napisu' using'. Jest prawdopodobne, że osoba dzwoniąca nadal musi odwoływać się do "arkusza roboczego" po zakończeniu twojej metody. – Keith

Odpowiedz

0

Spróbuj zwalniając obiektów COM wyraźnie:

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

Zostało wiadomo rozwiązać problemy z pamięcią w niektórych scenariuszach związanych biurowego.

+0

** Nie wiem, czy to naprawdę rozwiązuje problem, ponieważ nie mogę go odtworzyć. Ale to jak dotąd najlepsza odpowiedź. ** – jreichert