Threading Support in Office
This topic provides information about how threading is supported in the Microsoft Office object model. The Office object model is not thread safe, but it is possible to work with multiple threads in an Office solution. Office applications are Component Object Model (COM) servers. COM allows clients to call COM servers on arbitrary threads. For COM servers that are not thread safe, COM provides a mechanism to serialize concurrent calls so that only one logical thread executes on the server at any time. This mechanism is known as the single-threaded apartment (STA) model. Because calls are serialized, callers might be blocked for periods of time while the server is busy or is handling other calls on a background thread.
Knowledge Required When Using Multiple Threads
To work with multiple threads, you must have at least basic knowledge of the following aspects of multithreading:
Windows APIs
COM multithreaded concepts
Concurrency
Synchronization
Marshaling
For general information about multithreading, see Multithreading in Components.
Office runs in the main STA. Understanding the implications of this makes it possible to understand how to use multiple threads with Office.
Basic Multithreading Scenario
Visual Studio Tools for Office code always runs on the main UI thread. You might want to smooth out application performance by running a separate task on a background thread. The goal is to complete two tasks seemingly at once instead of one task followed by the other, which should result in smoother execution (the main reason to use multiple threads). For example, you might have your event code on the main Excel UI thread, and on a background thread you might run a task that gathers data from a server and updates cells in the Excel UI with the data from the server.
Background Threads That Call into the Office Object Model
When a background thread makes a call to the Office application, the call is automatically marshaled across the STA boundary. However, there is no guarantee that the Office application can handle the call at the time the background thread makes it. There are several possibilities:
The Office application must pump messages for the call to have the opportunity to enter. If it is doing heavy processing without yielding this could take time.
If another logical thread is already in the apartment, the new thread cannot enter. This often happens when a logical thread enters the Office application and then makes a reentrant call back to the caller's apartment. The application is blocked waiting for that call to return.
Excel might be in a state such that it cannot immediately handle an incoming call. For example, the Office application might be displaying a modal dialog.
For possibilities 2 and 3, COM provides the IMessageFilter interface. If the server implements it, all calls enter through the HandleIncomingCall method. For possibility 2, calls are automatically rejected. For possibility 3, the server can reject the call, depending on the circumstances. If the call is rejected, the caller must decide what to do. Normally, the caller implements IMessageFilter, in which case it would be notified of the rejection by the RetryRejectedCall method.
However, in the Visual Studio Tools for Office case, COM interop converts all rejected calls to a System.Runtime.InteropServices.COMException ("The message filter indicated that the application is busy"). Whenever you make an object model call on a background thread, you must to be prepared to handle this exception. Typically, that involves retrying for a certain amount of time and then displaying a dialog. However, you can also create the background thread as STA and then register a message filter for that thread to handle this case.
Starting the Thread Correctly
When you create a new STA thread, set the apartment state to STA before you start the thread:
Dim t As New System.Threading.Thread(AddressOf AnObject.aMethod)
t.SetApartmentState(System.Threading.ApartmentState.STA)
t.Start()
System.Threading.Thread t = new System.Threading.Thread(AnObject.aMethod);
t.SetApartmentState(System.Threading.ApartmentState.STA);
t.Start();
For more information, see Managed Threading Best Practices.
Modeless Forms
A modeless form allows some type of interaction with the application while the form is displayed. The user interacts with the form, and the form interacts with the application without closing. The Office object model supports managed modeless forms; however, they should not be used on a background thread.
See Also
Concepts
Creating Office Solutions in Visual Studio
Reference
Threading (C# Programming Guide)
Other Resources
Multithreading in Visual Basic
Change History
Date |
History |
Reason |
---|---|---|
August 2008 |
Added new links to IMessageFilter COM interface and its members. |
Information enhancement. |