HowTo: Work with threads in Microsoft Office COM add-ins
It is generally known that the Microsoft Office Object Model is not thread safe and accessing some object, property or method not from the main thread of a COM add-in may sometimes result in a host application crash. Of course, nobody prevents you from using threads inside the Office COM add-in itself, the threads that don’t need the Office Object Model.
In our today’s VB.NET example (a C# sample is available for download at the bottom of the page), we are going to fill in the DataGridView component, which is located in the Outlook Explorer window, with data by using a background thread. Here’s the code that runs the thread and adds a hundred lines to the DataGridView.Rows collection:
Private Sub startButton_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles startButton.Click startButton.Enabled = False myThread = New Thread(AddressOf StartThread) myThread.Start() End Sub Private Sub StartThread() SyncLock ThreadRunningObj FlagThreadRunning = True End SyncLock Try Dim nameColumn As String Dim timeStamp As String Dim boolColumn As Boolean = True For i As Integer = 1 To 100 nameColumn = "Record " & i.ToString() timeStamp = DateTime.Now.ToString() boolColumn = Not boolColumn AddRow(nameColumn, timeStamp, boolColumn) Thread.Sleep(1000) If Not FlagThreadRunning Then Exit Try End If Next SetEnabled(True) Finally SyncLock ThreadRunningObj FlagThreadRunning = False End SyncLock End Try End Sub
Naturally, besides launching we need to stop the thread. Let’s do it with some stop button:
Private Sub stopButton_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles stopButton.Click StopThread() startButton.Enabled = True End Sub Private Sub StopThread() SyncLock ThreadRunningObj FlagThreadRunning = False End SyncLock myThread.Join() End Sub
One more note. You have to stop the additional thread not only upon clicking the Stop button, but also when closing the host application. In our sample, it should be done in the Dispose method:
Protected Overloads Overrides Sub Dispose( _ ByVal disposing As Boolean) If disposing Then If myThread IsNot Nothing Then StopThread() End If If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub
That’s all for today. If you have any questions or comments, don’t hesitate to post them!
You may also be interested in:
How to create Office COM addin in .net
Build COM add-in for Office 2000 – 2007 in Delphi
Available downloads:
C# sample Outlook add-in for VS 2005
VB.NET sample Outlook add-in for VS 2005
Delphi sample Outlook add-in for Delphi 7
4 Comments
How about working with delphi 7 or 2009 ? I want to get an example similar to dot net.
Thanks your add in express.
There is one quite serious problem in Delphi. The TThread.Synchronize method does not work in a DLL. That is why “normal” synchronization is not possible. But you can use the PostMessage function to notify the main VCL UI thread that some changes were made in a background thread. Please see the new Delphi sample under Available downloads.
Would it warrant mentioning the .NET BackgroundWorker? Does using BackgroundWorker always ensures marshaling back to “UI” thread of the host application?
In these samples we don’t use the BackgroundWorker class. Of course, you can try to use it, but I am afraid you will have to synchronize manually.