现在,它输出00而不是54.我正在学习线程而且我在这里,我不知道该怎么做
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
Point[] array = new Point[20];
public Form1()
{
for (int i = 0; i < 20; i++)
{
array[i] = new Point(); // I'm creating objects here
}
InitializeComponent();
}
void function1()
{
array[0].x = 5;
array[0].y = 4;
}
void function2()
{
label1.Text = array[0].ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
Thread thread1 = new Thread(function1);
thread1.Start();
Thread.Sleep(500);
function2();
}
}
class Point
{
public int x;
public int y;
public override string ToString()
{
return x.ToString() + y.ToString();
}
}
}
当我这样做时(没有另一个线程)
private void Form1_Load(object sender, EventArgs e)
{
function1();
function2();
}
工作正常,输出为54 感谢
答案 0 :(得分:2)
你在做什么并没有多大意义。你正在启动一个线程,然后休眠500ms,然后调用使用该线程结果的函数。
这意味着您的两个操作依次依赖,无法并行执行。在这里使用线程毫无意义。
您没有看到更改的原因可能是因为thread1
没有足够的时间在睡眠完成之前启动并执行其代码并且function2
被调用。
尝试使用thread1.Join()
代替,但就像我说的,这根本没有意义!
答案 1 :(得分:2)
实际上您的程序正在按预期在我的计算机上运行。那么为什么它不能在您的计算机上工作(或者仅在有时工作)?这是因为您的计划中存在竞争条件。这意味着您的程序假定第二个线程(执行function1)将在不到500ms的时间内为数组分配新值。永远不要假设其他线程完成它的任务需要多长时间。操作系统可以自由选择单个线程执行的时间,频率和时间以及暂停时间。相反,使用同步原语(例如ManualResetEvent)来确保第二个线程完成了它的任务。
此代码显示,如何更改程序正确执行线程同步:
ManualResetEvent MRE = new ManualResetEvent(false);//Add this field to Form1
void function1()
{
array[0].x = 5;
array[0].y = 4;
MRE.Set();//This notifies first thread, that values are set.
}
private void Form1_Load(object sender, EventArgs e)
{
Thread thread1 = new Thread(function1);
thread1.Start();
MRE.WaitOne();//This makes this thread wait until the second thread calls MRE.Set()
function2();
}
答案 2 :(得分:1)
如果function2
取决于function1
的完成情况,那么您需要确保在function1
开始之前function2
确实完成。使用Thread.Sleep
进行该作业并不总是有效,因为线程的调度和执行方式不可预测。
Thread.Sleep
的另一个问题是它阻止了UI线程。在基于UI的应用程序中使用多线程时的首要规则是永远不会阻止UI线程。这适用于任何类型的屏蔽通话,包括Thread.Sleep
,ManualResetEvent
,Thread.Join
等。
我解决此问题的方法是使用Task
类和ContinueWith
方法。这将等待function1
完成,然后在不阻止UI线程的情况下调用function2
。
private void Form1_Load(object sender, EventArgs e)
{
TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
function1();
}).ContinueWith((task =>
{
function2();
}, ui);
}
答案 3 :(得分:0)
由于缺少';',您提供的代码将无法编译睡觉(500)电话。
当语法修复时,它在我的盒子上“起作用”。
你没有安全的信号表明它已经完成。你正在学习,第一课 - 不要等待带有sleep()调用的线程。
BackgroundWorker组件更易于使用 - 您不必担心显式信令以获得结果。
如果你想坚持使用Thread实例,请查看autoResetEvent类或Thread.Join()。