如何在不引用表单的情况下使用 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 在不刷新页面的情况下提交表单?