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!