如何更正每个新启动的线程使用新计数器的代码。当你开始一个新线程时,挂起旧线程,而不是继续。
感谢您的帮助。
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);
}
}
答案 0 :(得分:3)
你的旧线程没挂。问题出在你的计数器变量中。它由您共享。旧线程只在新线程的kolejka[counter]
上继续。我猜这不是你想要的。
在goThread方法的开头,您可以执行以下操作:
var item = kolejka[counter];
然后你可以使用item而不是kolejka [counter]。然而,这也不是线程安全的,但比现在好多了。
答案 1 :(得分:3)
问题是你正在增加counter
变量,但它在你的线程中使用。不要那样做。在您的情况下,为线程提供本地信息非常重要,因为您希望每个线程都在“自己的”计数器上工作。这可以这样实现:
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);
}
}
这将完成按钮事件中的所有初始化内容并传入info类的实例。该信息类获取线程需要的所有信息,但它是线程的本地信息!
答案 2 :(得分:0)
您的代码存在一些问题。
counter
而不会锁定两个线程。counter
值。为此,您不需要线程。最简单的方法是使用一个计时器。
伪:
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());
}
答案 3 :(得分:0)
跟进 Peter ,你可以在帖子的开头创建一个副本:
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);
}
}