I have a windows form with a text box txtOutput. I have some content in it. I have written a property to get and set the txtOutput.Text both from within the same thread and across threads like this:
public string OutputString
{
get
{
string text = string.Empty;
if (txtOutput.InvokeRequired)
{
txtOutput.BeginInvoke(new MethodInvoker(delegate
{
text = txtOutput.Text;
}));
}
else
{
text = txtOutput.Text;
}
return text;
}
set
{
if (txtOutput.InvokeRequired)
{
txtOutput.BeginInvoke(new MethodInvoker(delegate
{
txtOutput.Text = value;
}));
}
else
{
txtOutput.Text = value;
}
}
}
If I set/get the property from the same thread, the behavior is as expected when calling the below function like PrintMessage().
public void PrintMessage()
{
MessageBox.Show(OutputString);
}
But when I call like this new Thread(PrintMessage).Start(). The get does not retrieve the value in the text box (i.e., the MessageBox shows empty string). When I do the same by keeping a breakpoint on the line:
txtOutput.BeginInvoke(new MethodInvoker(delegate
{
text = txtOutput.Text;
}));
while debug, the value is retrieved (i.e., the MessageBox shows the txtOutput content)
Should I sleep somewhere? Where am I making the mistake?
The problem is you’re calling MessageBox.Show() with a reference to the text variable before the UI thread can handle the request you placed with the dispatcher. I would avoid using Thread.Sleep() as you could end up with some nasty side effects. Ideally you should re-factor your code to get rid of the property, which is synchronous, in favor of a more asynchronous solution. Something similar to the code below should give you the result you’re looking for:
And Invoke it: