办公室中的线程支持

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

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

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

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

  • Windows API

  • COM 多线程概念

  • 并发

  • 同步

  • 封送

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

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

基本多线程方案

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

调用办公室对象模型的后台线程

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

  1. 办公室应用程序必须泵送消息,以便调用有机会进入。 如果它正在执行繁重的处理而不产生这种情况可能需要时间。

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

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

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

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

正确启动线程

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

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

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

有关详细信息,请参阅托管线程处理的最佳做法

无模式窗体

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