Reputation: 1
How to correct the code that each newly launched thread use the new counter. At the moment when you start a new thread hangs the old, instead of going on.
Thanks for help.
private void button1_Click(object sender, EventArgs e)
{
thread[counter] = new Thread(goThread);
thread[counter].Start();
counter++;
}
private void goThread()
{
kolejka[counter] = new PictureBox();
kolejka[counter].Location = new Point(325, n - 150);
kolejka[counter].Image = threading.Properties.Resources.car;
kolejka[counter].Size = new Size(20, 37);
this.Invoke((MethodInvoker)delegate
{
this.Controls.Add(kolejka[counter]);
});
for (int i = 0; i < 500; i++)
{
this.Invoke((MethodInvoker)delegate
{
kolejka[counter].Location = new Point(kolejka[counter].Location.X, kolejka[counter].Location.Y - 3);
this.Refresh();
});
Thread.Sleep(50);
}
}
Upvotes: 0
Views: 172
Reputation: 56697
The problem is that you're increasing the counter
variable, but it is used within your threads. Don't do that. In your case it is very important to make information local to the thread, because you want each thread to work on "its own" counter. This can be achieved like this:
private class ThreadInfo
{
public PictureBox Picture;
public int Counter;
}
private void button1_Click(object sender, EventArgs e)
{
kolejka[counter] = new PictureBox();
kolejka[counter].Location = new Point(325, n - 150);
kolejka[counter].Image = threading.Properties.Resources.car;
kolejka[counter].Size = new Size(20, 37);
this.Controls.Add(kolejka[counter]);
ThreadInfo info = new ThreadInfo() {
Picture = kolejka[counter],
Counter = counter
};
thread[counter] = new Thread(goThread);
thread[counter].Start(info);
counter++;
}
private void goThread(object state)
{
ThreadInfo info = state as ThreadInfo;
for (int i = 0; i < 500; i++)
{
this.Invoke((MethodInvoker)delegate
{
info.Picture.Location = new Point(info.Picture.Location.X, info.Picture.Location.Y - 3);
this.Refresh();
});
Thread.Sleep(50);
}
}
This does all the initialization stuff in your button event and passes in an instance of an info class. That info class takes all the information the thread needs, but so that it is local to the thread!
Upvotes: 3
Reputation: 22038
Follow up on Peter, you could create a copy at the beginning of the thread:
private void button1_Click(object sender, EventArgs e)
{
ManualResetEvent threadStartedSignal = new ManualResetEvent(false);
thread[counter] = new Thread(goThread);
thread[counter].Start(threadStartedSignal);
// wait for the thread to create a local reference.
threadStartedSignal.WaitOne();
counter++;
}
private void goThread(object state)
{
kolejka[counter] = new PictureBox();
var myPictureBox = kolejka[counter];
// signal the other thread, that the counter may be changed.
((ManualResetEvent)state).Set();
myPictureBox .Location = new Point(325, n - 150);
myPictureBox .Image = threading.Properties.Resources.car;
myPictureBox .Size = new Size(20, 37);
this.Invoke((MethodInvoker)delegate
{
this.Controls.Add(myPictureBox );
});
for (int i = 0; i < 500; i++)
{
this.Invoke((MethodInvoker)delegate
{
myPictureBox.Location = new Point(myPictureBox.Location.X, myPictureBox.Location.Y - 3);
this.Refresh();
});
Thread.Sleep(50);
}
}
Upvotes: 0
Reputation: 22038
There are several problems with your code.
counter
without locking in two threads.counter
value in control.For this purpose, you don't need threads. The easiest way is using one timer.
PSEUDO:
List<Car> _myCars = new List<Car>();
private Form1()
{
_timer = new Timer();
_timer.Interval = 50;
_timer.Tick += Timer_Tick;
}
private void Timer_Tick(object sender, EventArgs e)
{
foreach(var car in _myCars.ToArray())
{
car.Location = new Point(car.Location.X, car.Location.Y - 3);
if(car.Location.Y < 0)
_myCars.Remove(car);
}
}
private void button1_Click(object sender, EventArgs e)
{
_myCars.Add(new Car());
}
Upvotes: 0
Reputation: 27944
Your old thread is not hanging. The problem is in your counter variable. It is shared by you threads. The old thread just continues on the kolejka[counter]
of the new thread. I guess that is not what your want.
In the beginning of your goThread method you can do something like:
var item = kolejka[counter];
And then you can use item instead of kolejka[counter]. However this is not thread safe yet either, but a lot better then you have now.
Upvotes: 3