Blackbriar
Blackbriar

Reputation: 507

Get text from TextBox from another thread

Inside a class I have got a 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;
    }
}

To access this TextBox safely from another Thread I would like to use the Invoke mechanism. But the function getTextFromBox() fails at the line where Invoke() is used. I verified this by putting a breakpoint at this line and pressing F10 (Step over). It fails without an exception. Is there a mistake at my way of invoking?

Edit

Why do I need to access a text box from another thread? I am trying to create a new thread on every button click to prevent my UI from freezing. E.g. on a user login window when the login button is pressed, a new thread is started that notifys and observer. The observer then wants to read the the values of the username- and password-textbox to check if the logintry is valid.

The strange thing about this: Writing to a textbox works without any problem. The code I use:

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

Upvotes: 1

Views: 3392

Answers (1)

dymanoid
dymanoid

Reputation: 15227

Generally speaking, it shouldn't be necessary to access the UI elements from worker threads.

You should change your approach. I suppose you're on .NET Framework 4.5 or newer, so there's a right pattern for you: TAP, more commonly known as async/await.

With this pattern, you don't care about the threads. The Framework cares about them for you. Your task is to tell the compiler, what needs to be performed as an asynchronous action.

Just an example - change the event handler of your Button's Click event to something like this:

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

Upvotes: 1

Related Questions