#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. Спасибо за ответ, я все это делаю. Снижает скорость добавления. Терпимо, но грустно.