【问题标题】:Instantiating Windows Form from macro in Excel causes dialog "microsoft excel is waiting for another application to complete an ole action"从 Excel 中的宏实例化 Windows 窗体会导致对话框“microsoft excel 正在等待另一个应用程序完成 ole 操作”
【发布时间】:2014-02-14 20:44:07
【问题描述】:

抱歉无法发布任何代码示例(我还不能提炼成一个小的、可重现的代码库,而且我拥有的代码是专有的)。

我的情况是这样的:我有一个使用 Excel DNA 开发的 Excel 加载项,它从需要身份验证的 REST Web 服务中提取数据。加载项按会话存储凭据,但不会在 Excel 实例之间保留。还存在一个向用户公开的宏,允许他们调用加载项中的代码以从 Web 服务中提取数据。

如果用户以前没有登录过,我们会弹出一个 Windows 窗体对话框,要求提供凭据。这工作正常。成功登录后,我们的逻辑开始(在一个测试中,有 6 个并发请求)从 Web 服务中提取数据。有一点来回(请求数据,它是未经授权的,登录,再次请求,拉数据等)。如果登录以编程方式发生(没有显示或实例化 Windows 窗体),则一切正常。

我看到的问题是,当涉及 Windows 窗体时,我看到授权请求和取回数据之间存在 1 分钟 29 秒的延迟(加/减几分之一秒)。此延迟最终导致 Excel 对话框:“microsoft excel 正在等待另一个应用程序完成 ole 操作”。另一个奇怪的事情是我们所做的一切实际上都成功地发生了,用户刚刚得到这个对话框并且必须点击“确定”(并且经历了不必要的延迟)。

所有迹象都表明延迟发生在客户端。如果我完全删除了 Windows 窗体登录对话框,我们不会看到任何延迟,并且所有操作都已完成,并且在 excel 中根本没有任何提示。

一时兴起,我完全删除了使用实际凭据进行提示的代码,并硬编码了我们测试帐户的凭据。而且,它工作正常。如果我采用完全相同的代码并仅实例化一个空白 Windows 窗体,即 new System.Windows.Forms.Form(); 并且不对其执行任何操作,我会在我们的请求中获得完全相同的行为,一切都会阻塞 1 分 29 秒。然后,我们的请求成功了,但是客户端得到了前面提到的 Excel 对话框。

我们还通过功能区控件公开了完全相同的功能,可以正常工作,唯一的两个区别是:1. 不涉及宏,2. 我们在工作进行时显示进度对话框。

我们已验证所有 UI 元素都在 Excel 主线程上呈现/处理,并且我们不做任何与 Excel 交互的操作,除了在主线程上。没有引发异常(在调试器下运行时验证,所有异常都抛出中断)。

我以为我们做错了什么,直到我实例化了一个空白的 Windows 窗体(请注意 - 它甚至从未显示,只是实例化)并且我可以重现该行为。

有没有人看到这个或知道如何解决?

【问题讨论】:

    标签: c#-4.0 excel excel-2013 vba


    【解决方案1】:

    这不是一个答案,但我认为它不适合作为评论。另外,根据目前的信息,我不确定答案是否可能。

    是的,当然,代码是专有的。但是,您将不得不展示其中的一些内容,否则这将无济于事。我现在能做的就是提供一些可以看的东西。

    使用插件可能很难知道您实际在哪个线程上。就在您创建登录表单之前,请输入以下几行:

        ApartmentState threadState = Thread.CurrentThread.GetApartmentState();
        if (threadState != ApartmentState.STA)
        {
            // put a break or some warning like console.Writeline(threadState);
        }
    

    如果它不是 STA 线程,则无法实例化窗口消息泵 - 好吧,这太强了:消息泵应该只在 STA 线程上,虽然我认为它们可以在 MTA 线程上,但会导致问题。

    如果你有一个 UI 元素的引用,继承自 Control 的东西,你可以检查它是否需要 Invoking 来改变它:

    if (control.InvokeRequired)
    {
        // You're not on the GUI thread
    }
    

    如果其中任何一个失败,你可能不在你认为的线程上。

    你能确定延迟在哪里吗?您说您正在使用 Windows 窗体来获取凭据。您可以调试代码并逐步查看延迟发生的位置吗?也许从 Show()ing 表单之前到它回到主代码路径时一步一步?能否展示一下延迟发生的代码?

    只是一些事情要尝试。

    【讨论】:

    • ApartmentState 出现在我的脑海中。我还没有验证它是什么(我明天会破解)。我发现的另一个奇怪之处(这是我现在的“修复”)是 WPF 似乎没有同样的问题。至于延迟发生的位置,它是在初始 REST 请求登录到 Web 服务以建立会话之后(请注意,我们在 6 个不同的线程/会话中异步执行此操作)。所有的请求都在收到初始登录成功后挂起,但在我们真正发送真正的请求之前。调试器显示等待任务完成; http 跟踪显示完成。
    • 我确实验证了ApartmentStateSTA
    猜你喜欢
    • 2014-04-18
    • 2014-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    • 1970-01-01
    相关资源
    最近更新 更多