【问题标题】:How to use ISynchronizeInvoke without a reference to the Form如何在不引用表单的情况下使用 ISynchronizeInvoke
【发布时间】: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 一样简单,它不需要任何对表单的引用。所以我会在谷歌上搜索更多关于如何使用它的信息。

【问题讨论】:

    标签: c# multithreading .net-3.5


    【解决方案1】:

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

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

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

    【讨论】:

    • 哦,我明白了,获取 SynchronizationContext 对象看起来相当简单,因此即使没有对表单的引用也应该可以工作。
    • 要小心,因为在辅助线程上使用 SynchronizationContext.Current 不会获得您想要的上下文,这就是为什么我建议在应用程序启动时从主线程存储它。
    • 好点,同时也在网络资源中阅读了该警告。
    猜你喜欢
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    • 2016-11-16
    • 2012-03-04
    • 1970-01-01
    • 2013-04-04
    相关资源
    最近更新 更多