与Windows应用程序相比,插件访问速度快15-20倍

时间:2018-06-04 14:13:54

标签: c# performance office-interop word-addins

我不知道,如果StackOverflow是关于性能问题的正确的地方,但我还没有找到任何更好的社区来解决这个问题。

基本上我们有两个示例程序,一个是插件,一个是引用Word互操作的winforms程序。

两者都实现了名为public class SlowExample { public static void GetTabsFromParagraph(Paragraph para, Style style, List<Tabulator> tabList, bool getTabsForCase = false) { foreach (TabStop tab in para.TabStops) { if (tab.CustomTab) { bool showTab = true; foreach (TabStop ts in style.ParagraphFormat.TabStops) { if (Math.Abs(ts.Position - tab.Position) < 0.001 && ts.Alignment == tab.Alignment) { showTab = false; break; } } if (showTab || getTabsForCase) { Tabulator t = new Tabulator { Tabulatorausrichtung = tab.Alignment == WdTabAlignment.wdAlignTabLeft ? TabulatorAusrichtung.Links : TabulatorAusrichtung.Rechts, Tabulatorart = TabulatorArt.Tabulator, Position = tab.Position }; tabList.Add(t); } } } if (!getTabsForCase) { foreach (TabStop ts in style.ParagraphFormat.TabStops) { if (ts.CustomTab) { bool showTab = true; foreach (TabStop tab in para.TabStops) { if (Math.Abs(tab.Position - ts.Position) > 0.0001 || tab.Alignment != ts.Alignment) { showTab = false; break; } } if (showTab) { Tabulator t = new Tabulator { Tabulatorausrichtung = TabulatorAusrichtung.Geloescht, Tabulatorart = TabulatorArt.Tabulator, Position = ts.Position }; tabList.Add(t); } } } } if (Math.Abs(para.LeftIndent - style.ParagraphFormat.LeftIndent) > 0.001 || getTabsForCase) { Tabulator t = new Tabulator { Tabulatorausrichtung = TabulatorAusrichtung.Links, Tabulatorart = TabulatorArt.Einzug, Position = para.LeftIndent }; tabList.Add(t); } if (Math.Abs(para.RightIndent - style.ParagraphFormat.RightIndent) > 0.001 || getTabsForCase) { Tabulator t = new Tabulator { Tabulatorausrichtung = TabulatorAusrichtung.Rechts, Tabulatorart = TabulatorArt.Einzug, Position = para.RightIndent }; tabList.Add(t); } if (Math.Abs(para.FirstLineIndent - style.ParagraphFormat.FirstLineIndent) > 0.001 || getTabsForCase) { Tabulator t = new Tabulator { Tabulatorausrichtung = TabulatorAusrichtung.ErstzeilenEinzug, Tabulatorart = TabulatorArt.Einzug, Position = para.FirstLineIndent }; tabList.Add(t); } } public class Tabulator { private TabulatorArt m_Tabulatorart; private TabulatorAusrichtung m_Tabulatorausrichtung; private float m_Position; private bool m_UebernahmeInFolgedokument = false; public float Position { get { return m_Position; } set { m_Position = value; } } public float PositionOrg { get; set; } public float PositionInCm { get { return (m_Position / 28.35F); } set { m_Position = value * 28.35F; } } public TabulatorArt Tabulatorart { get { return m_Tabulatorart; } set { m_Tabulatorart = value; } } public TabulatorAusrichtung Tabulatorausrichtung { get { return m_Tabulatorausrichtung; } set { m_Tabulatorausrichtung = value; } } public TabulatorAusrichtung TabulatorausrichtungOrg { get; set; } public bool UebernahmeInFolgedokument { get { return m_UebernahmeInFolgedokument; } set { m_UebernahmeInFolgedokument = value; } } } public enum TabulatorArt { Invalid = 0, Tabulator = 1, Einzug = 2 } public enum TabulatorAusrichtung { Invalid = 0, Links = 1, Rechts = 2, ErstzeilenEinzug = 3, Geloescht = 4, } } 的相同方法:

    private void TestSlowMethod(Word.Document document)
    {
        Word.Paragraphs documentParagraphs = document.Paragraphs;
        List<Tabulator> tabList = new List<Tabulator>();
        long swElapsedMilliseconds = 0;
        foreach (Word.Paragraph documentParagraph in documentParagraphs)
        {
            Word.Style style = documentParagraph.get_Style();

            Stopwatch sw = new Stopwatch();
            sw.Start();

            SlowExample.GetTabsFromParagraph(documentParagraph, style, tabList, true);

            sw.Stop();
            swElapsedMilliseconds += sw.ElapsedMilliseconds;
            Debug.WriteLine(sw.ElapsedMilliseconds + "\r\n");
        }

        MessageBox.Show("Total ms: " + swElapsedMilliseconds);
        Debug.WriteLine("Done...");
    }

在这两个程序中,我加载一个应用程序,打开一个带有几个段落和标签的文档,并为每个段落运行此方法,如下所示:

f() {
   for ((i=1;i<$(($#+1));++i)); do
     echo -n "$i"
     echo -ne "\x00"
     echo -n "${!i}"
     echo -ne "\x00"
   done
}

f a b c | hexdump -C
00000000  31 00 61 00 32 00 62 00  33 00 63 00              |1.a.2.b.3.c.|
0000000c

我发现的是,插件正在运行,所有这一切都要快10-20倍。

  • 加入:每次通话20-30毫秒
  • WinForms工具:每次通话200-300毫秒

为什么?我的假设是,addin在与应用程序一词相同的上下文/进程中运行。但这是真正的原因吗?

我们可以解决这个问题吗?我们的软件从插件转移到WPF + Interop-Word。

提前致谢!

1 个答案:

答案 0 :(得分:1)

一些性能修复:

在这里稍早检查getTabsForCase

    if (tab.CustomTab)
    {
        bool showTab = true;

        if (getTabsForCase) //insert this here, no need to run if getTabsForCase.
            foreach (TabStop ts in style.ParagraphFormat.TabStops)
            {
                if (Math.Abs(ts.Position - tab.Position) < 0.001 &&
                    ts.Alignment == tab.Alignment)
                {
                    showTab = false;
                    break;
                }
            }
        if (showTab || getTabsForCase)
        {
            Tabulator t = new Tabulator
            {
                Tabulatorausrichtung = 
                    tab.Alignment == WdTabAlignment.wdAlignTabLeft
                        ? TabulatorAusrichtung.Links 
                        : TabulatorAusrichtung.Rechts,
                Tabulatorart = TabulatorArt.Tabulator,
                Position = tab.Position
            };

            tabList.Add(t);
        }
    }

同样,在getTabsForCase语句中的所有计算之前检查if

//see getTabsForCase goes first
if (getTabsForCase || Math.Abs(para.LeftIndent - style.ParagraphFormat.LeftIndent) > 0.001)

将所有这些条件修复为首先getTabsForCase - 然后语句的其余部分不需要进行评估。