从单独的静态类在控件线程的上下文中调用控件的方法

本文关键字:控件 调用 方法 上下文 线程 静态类 单独 | 更新日期: 2023-09-27 18:25:19

我有一个表单和一些控件:

public class Tester : Form
{
    public Label Demo;
    public Label GetDemo()
    {
        return Demo.Text;
    }
}

此外,我还有一些静态类:

public static bool Delay(Func<bool> condition)
{
    bool result = false;
    AutoResetEvent e = new AutoResetEvent(false);
    Timer t = new Timer(delegate {
        if (result = condition()) e.Set(); // wait until control property has needed value
    }, e, 0, 1000);
    e.WaitOne();
    t.Dispose();
    return result;
}

在某个时刻,控制创建新的线程并调用我们的静态方法:

ThreadPool.QueueUserWorkItem(delegate {
    if (Delay(() => GetDemo() == "X")) MessageBox.Show("X");
}, null);

当然,这将导致异常,因为GetDemo将被传递给Delay,并将在新线程中作为委托进行调用。

当然,可以通过使用Invoke调用我们的静态方法来解决这个问题:

ThreadPool.QueueUserWorkItem(delegate {
    Invoke((MethodInvoker) delegate {
        if (Delay(() => GetDemo() == "X")) MessageBox.Show("OK");
    }
}, null);

不幸的是,我不允许更改延迟调用,我只能更改它的实现。

问题:

1) 内部静态方法Delay需要更改什么,以便condition()在其本机线程中执行GetDemo而不会出现异常?

2) 有可能在Delay内部做这样的事情吗?

SynchronizationContext.Dispatcher((Action) delegate {  
    if (condition()) e.Set();
});

从单独的静态类在控件线程的上下文中调用控件的方法

此解决方案假设代码中的其他位置可以接收UI线程上的早期调用,以保存UI SynchronizationContext的副本。事实可能并非如此,在这种情况下,我提出的解决方案将不起作用。

// Assign this using SynchronizationContext.Current from a call made on the UI thread.
private static SynchronizationContext uiSynchronizationContext;
public static bool Delay(Func<bool> condition)
{
    bool result = false;
    AutoResetEvent e = new AutoResetEvent(false);
    Timer t = new Timer(delegate 
    {
        uiSynchronizationContext.Send(s => result = condition(), null);
        if (result)
            e.Set(); // wait until control property has needed value
    }, e, 0, 1000);
    e.WaitOne();
    t.Dispose();
    return result;
}