2011-05-09 65 views
0

嗨 我写了这个小的AddIn样本向您展示性能问题以及如何避免它VSTO Excel对象性能问题

有人能解释我为什么,它是如何工作的?

它只是一个excel工作簿的解析,运行在主excel进程(0)和计时器创建的随机线程中。

谢谢!

Public Class ThisAddIn 

Dim a As System.Windows.Threading.Dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher() 
Dim t As New Threading.Thread(New Threading.ParameterizedThreadStart(AddressOf threadTest)) 
Dim tm As New System.Timers.Timer(20000) 
Delegate Sub TestHandler() 
Dim tt As TestHandler = AddressOf test 

Private Sub ThisAddIn_Startup() Handles Me.Startup 
    tm.AutoReset = True 
    tm.Start() 
    AddHandler tm.Elapsed, AddressOf threadTest 
End Sub 

Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown 

End Sub 

Public Sub test() 
    Dim appE As Excel.Application = Globals.ThisAddIn.Application 
    Dim wb As Excel.Workbook = appE.ActiveWorkbook 
    Dim ws As Excel.Worksheet = wb.ActiveSheet 
    Dim rng As Excel.Range = ws.Cells(1, 1) 

    Dim nbit As Integer = 10000 
    For i = 1 To nbit 
     rng.Value = i 
    Next 
End Sub 

Private Sub threadTest() 
    ' 800 ms 
    Dim o() As Object 
    a.Invoke(tt, o) 

    '12 seconds ! 
    test() 

End Sub 
End Class 
+0

你问我们想知道你的加载项是否工作,为什么?看起来你会是最能做到这一点的人。 – IAmTimCorey 2011-05-09 14:51:20

+0

我在这里看不到任何工作表的解析。我所看到的是,你正试图在一个线程调用的for循环中写入一个从1到10,000的数字到单元格A1。 – code4life 2011-05-09 15:01:35

+0

还有一件事要认识到,每次你调用rng.Value时,这实际上是一个你正在做的COM函数调用。在VSTO中,降低性能开销的最佳方法是尽可能减少整体COM函数调用。 – code4life 2011-05-09 15:03:00

回答

1

您正在潜入COM线程模型的世界。这是一个很好的开始:http://msdn.microsoft.com/en-us/library/ms693344(VS.85).aspx

如果代码在Excel主线程(通过设置Dispatcher实现)上运行,则COM调用不会跨不同线程编组。由于您有很多COM调用(每个.Value算作一个),开销会增加您看到的差异。

在这种情况下编组成本高昂的原因之一是Excel COM对象在单线程单元(STA)中运行,这意味着有一个消息循环设置(实际上是一个Windows消息循环)在Excel中以序列化COM调用。每个跨公寓调用的结果都会将消息发布到此消息循环中,这是在主Excel线程上处理的。

因此,由于COM跨公寓编组,所以这两种情况的性能不同。这实际上非常快,考虑到幕后发生的事情。

在这两种情况下,进行单个调用以将大范围的.Value设置为值数组将更快。对于将数据设置到Excel表格中的最快(每秒百万个单元格)的方式,请参阅此处:Fastest way to interface between live (unsaved) Excel data and C# objects

+0

感谢您的回复! – Avlin 2011-05-09 15:49:33