繁体   English   中英

如何访问UI线程上的值?

[英]How can I access values on the UI thread?

我没有问题通过BeginInvoke调用UI控件上的操作等,但是,这是一个void方法。 我需要从文本框中获取一个值,以便在不同的线程中使用。

我怎么能做到这一点?

最简单的解决方案是在闭包中捕获局部变量。

String text;
textBox.Invoke(() => text = textBox.Text);

编译器将生成一些类似于chibacity的解决方案的代码 - 局部变量成为编译器生成的类的字段。

UPDATE

这不起作用 - lambda表达式不能赋予Delegate 可以使用扩展方法解决此问题。

internal void ExecuteOnOwningThread(this Control control, Action action)
{
    if (control.InvokeRequired)
    {
        control.Invoke(action);
    }
    else
    {
        action();
    }
}

用法如下。

String text;
textBox.ExecuteOnOwningThread(() => text = textBox.Text);

可以将多个语句填充到lambda表达式中。

textBox.ExecuteOnOwningThread(() =>
{
    DoStuff();
    text = textBox.Text
    DoOtherStuff();
});

但是,正如评论中已经提到的那样,明确地编写方法可能会更好。 使用lambda表达式超出某一点会对代码的可读性产生负面影响。 使用lambda表达式当然很容易引入重复的代码。

Control.Invoke()方法返回被调用方法的值。 这简单易行:

        string value = (string)this.Invoke(new Func<string>(() => textBox1.Text));

或者更明确一点:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
        var dlg = new Func<string>(GetText);
        string value = (string)this.Invoke(dlg);
    }
    private string GetText() {
        return textBox1.Text;
    }

您可以将委托传递给Invoke,该委托指向可以设置实例变量以保存文本值的方法,例如

    public Form1()
    {
        InitializeComponent();

        Invoke(new Action(SetTextboxTextVariable));
    }

    private string _text;

    private void SetTextboxTextVariable()
    {
        _text = txtBox.Text;
    } 

这涵盖了基本思想,同步和通知其他线程取决于您。 :)

更新

或者一步到位:

    public Form1()
    {
        InitializeComponent();

        string text = GetText();
    }

    private string GetText()
    {
        string text;

        Invoke(new Action(text = txtBox.Text));

        return text;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM