我正在开发一个应用程序,其中两个线程同时从一个类执行一个方法。此方法执行一些复杂的计算,结果显示在WinForm中。
所以我的班级看起来像:
class Comp_func
{
/* Constructor */
public Comp_func()
{
}
public void THE_Complex_func(string One, Int16 Two, Int32 Three)
{
Calculate_this(One);
Thread.Sleep(10);
Calculate_that(Two);
Thread.Sleep(10);
Calculate_thatThat(Three);
Thread.Sleep(10);
Update_lable_in_form(value);
Thread.Sleep(10);
}
}
每个线程更新WinForm中的不同Label
所以,我希望没有关于线程同步的问题(因为我使用了线程安全方法)。
我的需求是这些更新应该同时发生(至少似乎同时发生)。
当用户点击表单中的“计算”按钮时,我会执行以下操作:
Comp_func Func1_class = new Comp_func();
Comp_func Func2_class = new Comp_func();
Thread Func1_Thread = new Thread(() => Func1_class.Start_Test("Blah", 2,3));
Thread Func2_Thread = new Thread(() => Func2_class.Start_Test("BlahBlah", 4,5));
//Func1_Thread.Priority = ThreadPriority.Highest; /* Deleted after Comments */
// Func2_Thread.Priority = ThreadPriority.Highest; /* Deleted after Comments */
Func1_Thread.Start();
Func2_Thread.Start();
/*
// Removed after Comments
// Let only Threads Run
while(true)
{
Application.DoEvent();
Update();
}
for(count = 0; count < 100; count++)
{
console.WriteLine("I WON'T USE WHILE(1) loops with DOEVENTS");
}
*/
我的问题是,当线程1的执行完成时,它会更新Label
,然后线程2启动并执行。
为了避免这种行为,我几乎在每一行之后写了Thread.Sleep();
。它仍然表现得好像windows没有注意切换!
知道为什么会这样吗?
提前致谢!
答案 0 :(得分:4)
您的代码示例非常不完整 - 因此很难看到发生了什么。
我的第一个评论是你的点击处理程序不应该有一个无限循环 - 实际上你根本不需要while(true)..DoEvent()
代码
为了响应您的要求,两个标签同时更新,最好的办法是让线程在更新UI之前加入 - 一种方法是创建一个开始其他两个线程的BackgroundWorker,Join( )s,然后使用两个结果更新UI - 根据您运行的.net版本,您可以使用Tasks库以较少的代码执行此操作。
这是一个相当粗略的实现(如果您没有可用的任务库):
private void button1_Click(object sender, System.EventArgs e)
{
BackgroundWorker master= new BackgroundWorker();
master.DoWork += (sender1, e1) =>
{
Thread t1 = new Thread(Func1_class.Start_Test);
Thread t2 = new Thread(Func1_class.Start_Test);
t1.Start();
t2.Start();
t1.Join();
t2.Join();
};
master.RunWorkerCompleted += (sender2, e2) =>
{
label1.Text = "text";
label2.Text = "text";
};
master.RunWorkerAsync();
}
答案 1 :(得分:2)
按照@dice的建议摆脱sleep()调用和DoEvents()循环 - 无论你认为它们有多少,它们都没有帮助。如果你正确调用/ BeginInvoke-标签更改,你应该没问题 - 只需退出OnClick事件处理程序。您不应该在GUI事件处理程序中等待。
重复 - 不要尝试在GUI事件处理程序中等待。
您拥有多少个处理器核心,为什么提高了工作线程的优先级?如果你只有一个CPU而你在Func1_Thread上启动一个CPU密集型任务,它将使用100%CPU运行,直到它自动停止或Windows反饥饿算法在30秒后给其他线程几个周期。这会给人一种序列化的印象。
将线程提升到高优先级然后插入sleep()调用只是......好吧,就是不要这样做!
答案 2 :(得分:1)
你真的不了解线程。
您无法确定操作系统将如何处理线程的执行。 如果你想同时更改标签,你必须自己做。
例如,在你的超级函数结束时引发一个事件,例如,让我们称之为SuperCalcDone。 在SuperCalcDone处理程序上,只需检查所有计算是否完成,然后更新标签。