Почему InlineShape.add в Word2013 приводит к утечке памяти

#vba #memory-leaks #ms-word

#vba #утечки памяти #ms-word

Вопрос:

Моя программа должна добавлять фотографии в таблицу документов Word. Столкнулся с тем, что в Word 2013 программа работает намного медленнее или даже зависает. Я начал искать проблемные области, и кажется, что проблема в памяти, занятой при добавлении изображений.

Я добавляю изображения в таблицу Word 2013 InlinesShapes.AddPicture методом. после этого используемая память увеличивается на ~ 50 Мб для каждого изображения. Когда он достигает ~ 600 Мб, он перестает расти с такой скоростью, и рост составляет около 1 МБ. Затем в какой-то момент Word очищает память до 200 и снова.

Но если я сделаю то же самое в Word 2007, объем заблокированной памяти будет меньше 1 КБ, все время.

Word 2007 на моем ноутбуке (Win 8.1, i5-4300u), Word 2013 устанавливается на другой компьютер (виртуальный рабочий стол с Win 7, Xeon E5) — если это имеет значение.

Я добавляю обычные фотографии, сделанные с помощью камеры, например: 4160×3120, 72 dpi, 24 бит, размер 500 Кб, JPG.

Этот пример кода с вычислением используемой памяти

 Sub A()  
    ' >-- SOME CODE --<

    Dim objCell As Word.Cell
    'user method that return first free Word.Cell from table
    Set objCell = TableManager.Get_FreeCell(objTable) 
    'clear
    Tools.MemCheck "<- mem before paste"

    objCell.Range.InlineShapes.AddPicture sFilePath 

    'clear
    Tools.MemCheck "-> mem after paste"

    ' >-- SOME CODE --<

    Set objCell = Nothing
 End Sub
  

Вывод по Word2013

     296.156 Mb <- mem before paste
    345.793 Mb -> mem after Paste
    346.504 Mb <- mem before paste
    396.18  Mb -> mem after Paste
  

Вывод по Word2007

     109.867 Mb <- mem before paste
    109.871 Mb -> mem after Paste
    109.871 Mb <- mem before paste
    109.879 Mb -> mem after Paste
    109.887 Mb <- mem before paste
    109.887 Mb -> mem after Paste
  

Существует код MemCheck. Объявил mobjSWbemServices как глобальные, чтобы исключить его из проблемы.

 Dim mobjSWbemServices as Object
Sub MemCheck(Optional ByVal sDescription As String = vbNullString)
    If mobjSWbemServices is nothing then Set mobjSWbemServices = GetObject("winmgmts:")
    Dim GetMemUsage As Double
     GetMemUsage = mobjSWbemServices.Get( _
        "Win32_Process.Handle='" amp; _
        GetCurrentProcessId amp; "'").WorkingSetSize / 1024 / 1024    

    Debug.Print Round(GetMemUsage, 3); " Mb"; vbTab; sDescription
   'GetCurrentProcessId  is Declared Library: 
     'Private Declare PtrSafe Function GetCurrentProcessId Lib "kernel32" () As Long
     'Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
End Sub
  

Итак, в чем может быть проблема? Я делаю что-то не так или это ошибка, и мне нужно установить некоторые обновления?

Ответ №1:

В графическом движке, используемом между Word 2007 (и 2010) и Word 2013 (и более поздними версиями), произошли серьезные изменения. Это может быть фактором. Насколько я помню, объектная модель работает медленнее в Word 2013 (и более поздних версиях), отчасти по соображениям безопасности. Так что, возможно, вы мало что можете сделать.

Одна вещь, которую вы можете попробовать, это очистить стек отмены Word и явно СОХРАНИТЬ документ. Это уменьшит количество объектов, которыми управляет Word, для поддержки отмены и может ускорить процесс.

Комментарии:

1. Спасибо за ответ, я все это делаю. Снижает скорость добавления. Терпимо, но грустно.