Office 中的线程支持

本文提供有关 Microsoft Office 对象模型中如何支持线程处理的信息。 Office 对象模型不是线程安全的,但可以在 Office 解决方案中使用多个线程。 Office 应用程序是组件对象模型 (COM) 服务器。 COM 允许客户端在任意线程上调用 COM 服务器。 对于非线程安全的 COM 服务器,COM 提供了一种序列化并发调用的机制,以便随时在服务器上只执行一个逻辑线程。 此机制被称为单线程单元模型(STA模型)。 由于调用已序列化,因此在服务器繁忙或正在处理后台线程上的其他调用时,调用方可能会阻塞一段时间。

适用于: 本主题中的信息适用于文档级项目和 VSTO 外接程序项目。 请参阅 Office 应用程序和项目类型提供的功能

使用多个线程时所需的知识

若要处理多个线程,必须至少了解多线程的以下方面:

  • Windows API

  • COM 多线程概念

  • Concurrency

  • Synchronization

  • 编组

    有关多线程的一般信息,请参阅 托管线程处理

    Office 在主 STA 中运行。 了解这一点的含义,可以了解如何将多个线程与 Office 配合使用。

基本多线程方案

Office 解决方案中的代码始终在主 UI 线程上运行。 你可能希望通过在后台线程上运行单独的任务来平整应用程序性能。 目标是看似同时完成两个任务,而不是一个任务后紧接另一个任务,这样应能够带来更流畅的执行(这是使用多个线程的主要原因)。 例如,你可能在主 Excel UI 线程上具有事件代码,在后台线程上,你可能会运行从服务器收集数据的任务,并使用来自服务器的数据更新 Excel UI 中的单元格。

调用 Office 对象模型的后台线程

当后台线程调用 Office 应用程序时,该调用会自动封送到 STA 边界。 但是,不能保证 Office 应用程序能够在后台线程调用时处理该调用。 有几个可能的原因:

  1. Office 应用程序必须处理消息,以便呼叫有机会被接收。 如果它在进行密集计算任务而没有让步,这可能需要时间。

  2. 如果单元中已有另一个逻辑线程,则新线程无法进入。 当逻辑线程进入 Office 应用程序,然后重新进入调用方的公寓时,通常会发生这种情况。 应用程序阻塞状态下等待该调用返回。

  3. Excel 可能处于无法立即处理传入呼叫的状态。 例如,Office 应用程序可能显示模式对话框。

    对于 2 和 3 的可能性,COM 提供 IMessageFilter 接口。 如果服务器实现它,则所有调用都通过 HandleIncomingCall 方法输入。 对于可能 2,呼叫会自动被拒绝。 对于可能性 3,服务器可以拒绝呼叫,具体取决于情况。 如果呼叫被拒绝,呼叫方必须决定该怎么做。 通常,调用方实现 IMessageFilter,在这种情况下,它将通过 RetryRejectedCall 方法通知拒绝。

    但是,对于使用 Visual Studio 中的 Office 开发工具创建的解决方案,COM 互作会将所有被拒绝的调用转换为( COMException “消息筛选器指示应用程序繁忙”)。 每当对后台线程进行对象模型调用时,都必须准备好处理此异常。 通常,这涉及到持续重试一段时间,然后显示一个对话框。 但是,还可以将后台线程创建为 STA,然后为该线程注册消息筛选器来处理这种情况。

正确启动线程

创建新的 STA 线程时,请在启动线程之前将单元状态设置为 STA。 下面的代码示例演示如何执行此作。

System.Threading.Thread t = new System.Threading.Thread(AnObject.aMethod);

t.SetApartmentState(System.Threading.ApartmentState.STA);
t.Start();

有关详细信息,请参阅 管理线程最佳实践

无模式窗体

无模式窗体允许在显示窗体时与应用程序进行某种类型的交互。 用户与表单交互,窗体与应用程序交互,无需关闭。 Office 对象模型支持管理的无模式表单,但不应在后台线程上使用它们。