Add a control on a form from another thread

This is my first post on this site, which I have to say, great!

Well, this is my problem, and I really hope that someone can help me.

I tried to delay adding controls to my main form in order to speed up its start. Well, I am running in the following exception:

Cross-threading is not valid: The Form1 control is accessible from a stream other than the stream that was created on.

I tried to just solve the problem with a smaller example, but the problem remains. Here is my code:

using System; using System.Drawing; using System.Threading; using System.Windows.Forms; namespace AddConrolFromAnotherThread { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void AddButton() { if(this.InvokeRequired){ this.Invoke(new MethodInvoker(this.AddButton)); } Random random = new Random(2); Thread.Sleep(20); Button button = new Button(); button.Size = new Size(50,50); button.Location = new Point(random.Next(this.Width),random.Next(this.Height)); this.Controls.Add(button); } private void buttonStart_Click(object sender, EventArgs e) { Thread addControlThread = new Thread(new ThreadStart(this.AddButton)); addControlThread.Start(); } } } 

I used the Invoke method and checked if InvokeRequiered is true, but InvokeRequiered continues to be β€œtrue”. I really don't get it. At least I would expect a StackOverflow exception, as this is a recursion call.

So, if anyone encountered a similar problem, please, could you tell me what I did wrong?

Tanks, Igor!

+6
multithreading c # invoke
source share
3 answers

The problem in your code is that you add two buttons.

Put the code after the if block in the else block.

 private void AddButton() { if(this.InvokeRequired){ this.Invoke(new MethodInvoker(this.AddButton)); } else { Random random = new Random(2); Thread.Sleep(20); Button button = new Button(); button.Size = new Size(50,50); button.Location = new Point(random.Next(this.Width),random.Next(this.Height)); this.Controls.Add(button); } } 
+4
source share

Use anonymous methods instead. Explanation below.

If we have this form:

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Thread t = new Thread(new ThreadStart(Start)); t.Start(); } private void UpdateText() { button1.Text = "New Text"; } void Start() { UpdateText(); } } 

This will throw an exception.

Change UpdateText to:

 private delegate void MyDelegate(); private void UpdateText() { if (button1.InvokeRequired) { button1.Invoke(new MyDelegate(UpdateText)); } button1.Text = "New Text"; } 

or use an anonymous method:

 void Start() { this.Invoke((MyDelegate)delegate { UpdateText(); }); } private void UpdateText() { button1.Text = "New Text"; } 
0
source share

It’s very expensive to use a stream by simply adding a button! Use ThreadPool instead.

0
source share

All Articles