从另一个线程的 TextBox 中获取文本

Get text from TextBox from another thread

在 class 我有一个 TextBox:

public class TextBoxAdapter {

    private System.Windows.Forms.TextBox textBox;

    //...some code that initializes the textBox...

    public string getTextFromBox() {
        if( textBox.InvokeRequired )
            return (string)textBox.Invoke( (Func<string>)delegate { return textBox.Text; } );
        else
            return textBox.Text;
    }
}

要从另一个线程安全地访问此 TextBox,我想使用 Invoke 机制。但是函数 getTextFromBox() 在使用 Invoke() 的那一行失败了。我通过在此行放置一个断点并按 F10(跳过)来验证这一点。它毫无例外地失败了。是不是我的调用方式有误?

编辑

为什么我需要从另一个线程访问文本框?我试图在每次单击按钮时创建一个新线程,以防止我的 UI 冻结。例如。在用户登录 window 时,当按下登录按钮时,将启动一个新线程来通知和观察者。然后观察者想要读取用户名和密码文本框的值以检查登录是否有效。

奇怪的是:写入文本框没有任何问题。我使用的代码:

        if ( textBox.InvokeRequired ) {
            MethodInvoker setText = new MethodInvoker( () => {
                textBox.Text = text;
            } );
            textBox.BeginInvoke( setText );
        }
        else {
            textBox.Text = text;
        }

一般来说,应该没有必要从工作线程访问 UI 元素。

你应该改变你的方法。我想您使用的是 .NET Framework 4.5 或更新版本,因此有一个适合您的模式:TAP,通常称为 async/await.

使用此模式,您无需关心线程。框架会为您关心它们。您的任务是告诉编译器,什么需要作为异步操作执行。

举个例子 - 将 ButtonClick 事件的事件处理程序更改为如下内容:

async void LoginButton_Click(object sender, EventArgs e)
{
    // This runs on the UI thread
    string login = loginTextBox.Text;
    string password = pwdTextBox.Text;

    loginButton.Enabled = false;

    // This will be executed asynchronously, in your case - on a worker thread
    bool success = await Task.Run(() => myLoginProcessor.Login(login, password));

    // This runs again on the UI thread, so you can safely access your controls
    if (success)
    {
        labelResult.Text = "Successfully logged in.";
    }
    else
    {
        labelResult.Text = "Invalid credentials.";
    }

    loginButton.Enabled = true;
}