如何在不引用表单的情况下使用 ISynchronizeInvoke

Posted

技术标签:

【中文标题】如何在不引用表单的情况下使用 ISynchronizeInvoke【英文标题】:How to use ISynchronizeInvoke without a reference to the Form 【发布时间】:2011-04-21 05:16:24 【问题描述】:

我需要将一段代码从另一个线程(Excel 互操作)“发送”到 UI 线程以执行。通常你会在Form 上使用Invoke,它实现了ISynchronizeInvoke 接口:

public class MyForm : Form

    ...
    private void Button_Click(object sender, EventArgs e)
    
        SomeExcelWorkbook.OnBeforeClose += delegate(ref bool Cancel)
        
            this.Invoke(someCode);
        ;
    

不幸的是,在表单代码和定义事件处理程序的代码之间有一个抽象层,我当时没有对表单的引用:

public void CodeExecutedByUIThread()

    ISynchronizeInvoke sync;
    SomeExcelWorkbook.OnBeforeClose += delegate(ref bool Cancel)
    
        sync.Invoke(someCode);
    ;

当输入CodeExecutedByUIThread时,我们还在UI线程中,所以理论上所有需要的东西都应该在那里。不幸的是Form is the only class implementing that interface,是吗?

如何从 UI 线程中获取 ISynchronizeInvoke 显然 Thread.CurrentThread 没有提供它...

或者有没有办法获得SynchronizationContext?我将如何检索和使用它?

更新:哦,我明白了,获取 SynchronizationContext 对象看起来就像SynchronizationContext.Current 一样简单,它不需要任何对表单的引用。所以我会在谷歌上搜索更多关于如何使用它的信息。

【问题讨论】:

【参考方案1】:

总的来说,我认为两者都不可能。

这似乎是一个显而易见的答案,但我们在本例中使用的是在应用程序启动时将 SynchronizationContext 和对表单的引用(作为 ISynchronizeInvoke)存储在静态类中。

MainForm main = new MainForm();
EnvironmentService.UI = main;
EnvironmentService.UIContext = SynchronizationContext.Current;
Application.Run(main);

【讨论】:

哦,我明白了,获取 SynchronizationContext 对象看起来相当简单,因此即使没有对表单的引用也应该可以工作。 要小心,因为在辅助线程上使用 SynchronizationContext.Current 不会获得您想要的上下文,这就是为什么我建议在应用程序启动时从主线程存储它。 好点,同时也在网络资源中阅读了该警告。

以上是关于如何在不引用表单的情况下使用 ISynchronizeInvoke的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Django、Ajax、jQuery 在不刷新页面的情况下提交表单?

在不使用 JavaScript 的情况下,如何在选择字段集中时使 Enter 键提交表单?

如何在不重新加载的情况下提交表单? [复制]

如何在不使用表单的情况下从 jsp 调用 servlet

如何在不重新加载页面的情况下提交表单[重复]

如何在不实际使用 <form> 的情况下使用引导表单布局?