【发布时间】:2013-08-31 15:33:54
【问题描述】:
我在 Windows 窗体 C# 应用程序上的多线程应用程序有问题。该应用程序在多核机器上运行良好,但是当它在单核机器上运行时,所有线程都挂起。我用的是backgroundWorker,代码如下:
class custonTime // delay class
{
public void sleep_sec(int sleep)
{
int time_now = Environment.TickCount;
int time_sleep = sleep;
while ((Environment.TickCount - time_now) < time_sleep) ;
}
}
当我按下 UI 上的按钮时,标志 action 和 doAlways 设置为 true 并启动以下后台工作程序。 backgorundworker1 在其他人执行任务的正确时间等待并触发任务:
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
while(action)
{
if(doItAlways)
{
//do important tasks
}
if(task1)
{
//do things
task1 = false;
}
if(task2)
{
//do things
task1 = false;
}
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
task1=true;
manegerTimewr2.sleep_sec(12000);//call delay class to wait 12 secs
task2=true;
manegerTimewr2.sleep_sec(12000);//call delay class to wait 12 secs
}
我的延迟类不仅锁定了我的backgorundworker1,还锁定了backgroundworker2,这使得无法执行标志doItAlways 触发的任务,只有在while 循环完成时才会释放应用程序。
而且它只发生在单核机器上。
还有其他方法吗?一种直接而简单的方法来挂起一个线程直到经过一段时间而不阻塞其他线程?
注意Thread.Sleep 不起作用,因为不同机器上经过的时间差异太大。
【问题讨论】:
-
像这样一个非常紧凑的循环... while ((Environment.TickCount - time_now)
-
这正是发生的事情,我能做些什么来防止它?
-
这段代码的坏处不止一个。永远不要使用 bool 在线程之间发出信号,不能保证另一个线程可以看到值的变化。请改用 AutoResetEvent。并且永远不要编写热等待循环,至少使用 Thread.Sleep()。在这里使用两个线程根本没有意义,第一个可以简单地自行延迟。从您当地的图书馆或书店拿起一本关于线程的书,您根本没有做对。
-
对不起我的代码是垃圾 =D,但是已经在代码上实现了 AutoResetEvent,有点棘手但结果相同,线程睡眠不能使用,因为需要控制时间,两个线程都是必要的,因为我需要访问一个自动化系统,这不能通过不同的线程来完成
-
请解释“不同机器上经过的时间差异太大”。你自己的代码应该使用
TimeSpan.TicksPerSecond,如果它打算在所有可能的.NET实现上工作相同的话。您还应该将 .NET 和 TPL 中的各种 Timer 类视为管理任务的更好方法。
标签: c# multithreading winforms