I have this function in the main form:

public void Check()
{
	UpBox myClass = new UpBox();
	myClass.UpdateBox(listBox1,"Hello");
}
public void Initial()
{
	Thread thread = new Thread(new ThreadStart(Check));
	thread.Start();
}
class UpBox
{
	private delegate void Box(ListBox list, string text);
	public void Box2(ListBox list,string text)
	{
		list.Items.Add(text);
	}
	public void UpdateBox(ListBox list, string text)
	{
		this.Invoke(new Box(Box2),list,text);
	}
}

Now, as I'm inside a thread, I'd have to use Invoke method to insert items in a ListBox.Invoke doesnt work.
Anyone can give me a hand here?
This Class is in a separated *.cs file.

Thx.

Recommended Answers

All 21 Replies

This is the solution, and you do not need to use any threads. This will only complicate things (simples you dont need to use them).
This is the simple example of how to pass data (parameters) over forms and being showed:

//FORM 1:
 public partial class Form1 : Form
    {
        public static bool bForm2Opened { get; set; }
        Form2 form2;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string value = textBox1.Text;
            if (!bForm2Opened)
            {
                form2 = new Form2();
                form2.Show();
                bForm2Opened = true;
            }
            form2.PopulatingListBox(value);
            //clearing textBox:
            textBox1.Text = null;
            textBox1.Focus();
        }
    }

//FORM 2
 public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        public void PopulatingListBox(string value)
        {
            listBox1.Items.Add(value);
        }

        private void Form2_FormClosing(object sender, FormClosingEventArgs e)
        {
            Form1.bForm2Opened = false;
        }
    }

Hope it helps, if not let me knows,

Mitja

I have use Threads. I'll use it in a exe i'm making, and the exe will be multi threading...

So when you will create a new thread?
Thats important to know, that you know when to open new Form.
In use case new thread is starting all over again, when trying po send a value into listBox on Form2.
What about if you want to send 2nd value? Your code cannot do it.

Do you Want to create a new Thread and open Form2? This thread has to remain opened until form2 is opened?
When form2 closes, the thread closes as well?

Is that how it should be?

There isnt a Form2.
There is a button that, OnClick will start the thred.
That button will create a new instance of my Class (separated from the MainForm class) and execute some procedure.
e.g

public void ThreadSub()
{
	MyClass cl = new MyClass();
	cl.Start("Thread started!");
}
public void OnClickButton()
{
	Thread s = new Thread(new ThreadStart(ThreadSub));
	s.Start();
}

Lets assume I have a listBox in the Main form(there is only ONE form!) named lBox.
Then, the code from the Start() procedure, should insert the Thread Started! text into it.
Using Invoke, because I'm this will be executed inside a diffrent thread. More clear now?

I did an example which starts a new form2 (form2 opens) and sends some text over to a listBox (on form2).
Take a look at this code. If you cannot midify it to your needs, let me know, I`ll do exactly what you want:

//form1:
 public partial class Form1 : Form
    {
        delegate void MyDelegate(string msg);
        public static bool bForm2Opened { get; set; }
        Form2 form2;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {          
            if (!bForm2Opened)
                StartNewThread();
            else
                OpenForm2();           
        }

        private void StartNewThread()
        {
            form2 = new Form2();
            form2.Show();
            Thread thread = new Thread(new ThreadStart(OpenForm2));
            thread.Start();
            bForm2Opened = true;   
        }

        private void OpenForm2()
        {
            string value = this.textBox1.Text;
            form2.DoWork(value);
            //clearing textBox on form1:
            this.textBox1.Invoke(new MyDelegate(ClearingTextBox), new object[] { null });            
        }

        private void ClearingTextBox(string msg)
        {
            this.textBox1.Text = null;
            this.textBox1.Focus();
        }
    }

//form2:
 public partial class Form2 : Form
    {
        delegate void MyDelegate(string msg);

        public Form2()
        {
            InitializeComponent();
        }

        public void DoWork(string msg)
        {
            this.listBox1.Invoke(new MyDelegate(PopulatingListBox), new object[] { msg });                
        }

        private void PopulatingListBox(string msg)
        {
            this.listBox1.Items.Add(msg);
        }

        private void Form2_FormClosing(object sender, FormClosingEventArgs e)
        {
            Form1.bForm2Opened = false;
        }
    }

I think this cant help me, because there is no other form. I am using a Tab Control.
And I want to create a class to update a listbox, but using invoke because I'm running in a diffrent Thread.

There is a Form1.cs which have all the form codes.
Then, I created another *.cs file. MyClass.cs that have the Update() procedure with a string argument.
The Update have to update Form1 listBox with the argument passed.

If it isn't too much work for you to do, I'd be glad if you can help me to do, exactly, this.
Thanks.

Ok, I did what I think its best for you. I hope it will suits oyur needs. The code calculates values from 2 textBoxes and inserts the result into 3rd textBox. Calculation is done by creating a new thread. Showing the result needs a delegate.
All you have to do is to insert 3 textBoxes and a button on the form and insert integers (numbers only - becuase the code has no error cahtching yet) into textBox1 and textBox2. Then press button.

Its good to put some breakpoints in the code, that you will see how the code goes, and then go line by line with F11. This is the code:

public partial class Form1 : Form
    {
        delegate void MyDelegate(int value);
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(StartNewThread));
            thread.Start();
        }

        private void StartNewThread()
        {
            MyClass myClass = new MyClass();
            int a = Convert.ToInt32(textBox1.Text);
            int b = Convert.ToInt32(textBox2.Text);
            int[] array = new int[] { a, b };
            int c = myClass.Calculating(array);
            this.textBox3.Invoke(new MyDelegate(ShowResults), new object[] { c });
        }

        private void ShowResults(int value)
        {
            textBox3.Text = value.ToString();
        }
    }

    class MyClass
    {
        public int Calculating(int[] array)
        {
            return array[0] * array[1];
        }
    }

No, that is not what I meant. My class should update the listbox, not multiply two values..

So you would like from MyClass update listBox on Form1?
Why? This doesnt make any sence. Especially not in this kind of example we are doing. Do you have any other reasons to do so?

This is just an example that I can modify later to do my stuff. There are several checks in myClass and listBox needs to be updated (from myClass).

So what do you think about this? This code is actually calling From MyClass, a method on Form1 - like you said.

public partial class Form1 : Form
    {
        int oldValue;
        delegate void MyDelegate(int value);
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(StartNewThread));
            thread.Start();
        }

        private void StartNewThread()
        {
            MyClass myClass = new MyClass(this);
            int a = Convert.ToInt32(textBox1.Text);
            int b = Convert.ToInt32(textBox2.Text);
            int[] array = new int[] { a, b };
            myClass.Calculating(array);            
        }

        public void DoWork(int value)
        {
            this.textBox3.Invoke(new MyDelegate(ShowResults), new object[] { value });           
        }

        private void ShowResults(int value)
        {
            textBox3.Text = value.ToString(); 
        }
    }
    class MyClass
    {
        Form1 form1;
        public MyClass(Form1 _form1)
        {
            form1 = _form1;
        }

        public void Calculating(int[] array)
        {
            int value = array[0] * array[1];
            form1.DoWork(value);
        }
    }

Are you happy now?
Of not, I will need some more info to help you out.

Mitja

I could see the sub that updates the textbox is inside the form1.
Is it possible to transfer it to myClass?

No, because the control which you want to update is on form1. So method InvokeRequired() has to execute on form1.
There are ways to call textBox1 from MyClass, but I wouldn`t recomend you that - seriousely.

Hope this helps.
Mitja

Even if it isn't recomended, could you show me how to do it? Just for knoledge.
And, why its not recomended?

Not now, I have to go.. really. I someone else wont help, I`ll do it tomorrow.
Just for into: oyou have to set the control`s modifier as public, and this is not good - to acces to control over classes.
Maybe you can figure out how it goes.
Sorry, regards,
Mitja

I already tried that, and it didn't worked :B
But, I'll mark this Thread as Solved. Thanks for your help, and if you can show me how to do it from myClass I would be bery happy. =]

I think the problem with your original code is that you are invoking on the UpBox class.
This causes the invoke to execute on the thread that the UpBox is created.
To update the listbox you should invoke on the listbox.
Try this.

public void UpdateBox(ListBox list, string text)
  {
    list.Invoke(new Box(Box2),list,text); //<-- call invoke on the ListBox object.
  }

I already did it.. Thanks.

Did it work?

I changed the control to pulic in form1 design, and I did what I wanted to. I just cant see why doing this is not recomended.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.