簡體   English   中英

從單獨的靜態類在其線程的上下文中調用控件的方法

[英]Invoke method of the control in context of its thread from separate static class

我有一個表格和一些控制:

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);

不幸的是,我不允許更改Delay的調用,我只能更改其實現。

題 :

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM