Запись в текущий документ с помощью макроса Visual Studio чрезвычайно медленная, предложения по ускорению? - PullRequest
2 голосов
/ 12 января 2012

Как правило, у меня нет претензий к скорости Visual Studio, но если я напишу макрос, в котором записано около 100 строк кода, его выполнение займет 1-2 минуты.

Это не звучит правильно. Есть ли еще более удобный способ написания блоков кода?

Во-первых, я заметил, что он заполняет буфер отмены, как будто я просто набираю текст вручную. Могу ли я имитировать поведение копирования / вставки, которое намного быстрее?

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

Sub WriteManyLines()
    DTE.Commands.Raise("{AA61C329-D559-468F-8F0F-4F03896F704D}", 2, Customin, Customout)
    DTE.Commands.Raise("{AA61C329-D559-468F-8F0F-4F03896F704D}", 5, Customin, Customout)
    Dim sb As New StringBuilder()

    For i As Integer = 1 To 100
        sb.AppendFormat("public string Method{0:000}() {{ return ""Method{0:000}""; }}", i)
        sb.AppendLine()
    Next i
    DTE.ActiveDocument.Selection.Text = sb.ToString()
End Sub

Ответы [ 3 ]

4 голосов
/ 12 января 2012

Этот API очень обманчив, поскольку кажется, что вы заменяете выделенный текст фактическим результатом StringBuilder.Или короче, копия / вставка.Но на самом деле вы печатаете результат StringBuilder (вот почему вы видели, как буфер отмены заполняется данными).

Этот тип поведения верен для большей части опыта редактирования, который происходит из пространства имен DTE.Если вам интересны эзотерические подробности, я написал в блоге об этой общей проблеме некоторое время назад.

Чтобы исправить это, вам нужно отказаться от DTE и перейти в IVsTextLines или ITextBuffer (последний предпочтительнее)как это более новый управляемый API).Чтобы выйти из DTE, вы должны быть в состоянии выполнить следующие

var vsTextLines = DTE.ActiveDocument.Object("TextDocument") as IVsTextLines;

изменения на IVsTextLines, которые будут идти непосредственно в буфер и избежать издержек при наборе.

Если вы хотите полностью избежать DTE и COM, вы можете использовать IVsEditorAdaptersFactoryService для сопоставления уровня COM с новыми управляемыми API-интерфейсами 2010 года.Этот интерфейс обычно запрашивается через MEF, но я считаю, что вы также можете использовать IServiceProvider (который реализует DTE) и сделать для него QueryService вызов.

2 голосов
/ 27 августа 2013
'' SLOOOW!
 ' DTE.ActiveDocument.Selection.Text = str
'' LIGHTNING FAST
   Dim txtSel As TextSelection
   txtSel = DTE.ActiveDocument.Selection
   txtSel.Delete()
   txtSel.Insert(str, vsInsertFlags.vsInsertFlagsInsertAtEnd)
2 голосов
/ 28 марта 2012

Я столкнулся с той же проблемой, что и Абель, и благодаря подсказкам JaredPar я смог исправить это следующим образом: вместо использования IVsTextLines (которые доступны только при установленном VS-SDK), я просто используйте TextDocument и получите объект 'EditPoint' из этого. Мой код выглядит так:

Dim vsTextDoc As TextDocument = DTE.ActiveDocument.Object("TextDocument")
Dim epoint As EditPoint = vsTextDoc.StartPoint.CreateEditPoint
Dim strBuilder As StringBuilder = New StringBuilder

'append everything to the strBuilder and then
strBuilder.AppendLine("This is a line")
epoint.Insert(strBuilder.ToString())

И теперь кажется, что освещение быстро сравнивается с тем, что происходило раньше с этой DTE.ActiveDocument.Selection.Text штукой! Надеюсь, это поможет кому-то в будущем:)

...