在多线程应用程序窗体c上使用while循环锁定,阻塞单核机器上的所有线程
本文关键字:机器 单核 线程 循环 窗体 应用程序 多线程 while 锁定 | 更新日期: 2023-09-27 18:29:41
我在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
,并启动以下后台工作程序。后台工作人员1等待并在正确的时间启动任务,另一个执行任务:
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
无法工作,因为不同机器上所用的时间差异太大
问题是,BackgroundWorker
在内部使用一个线程池,该线程池通常包含与机器上的CPU/内核相同数量的线程。因此,在一台CPU机器上,只有一个线程处理BackgroundWorkers,我想它们是按顺序调度的,所以第一个线程运行两个sleep_sec
调用,只有之后,第二个线程才启动。
另一方面,在多核机器上,线程池中有更多的线程,因此它可以按预期工作
您可以使用"普通"Thread
(与Thread.Sleep
一起使用,不要使用while
循环)进行"等待",因为这不需要任何UI交互。您也可以只使用Timer
对象,它正是用于此目的(在指定的时间后触发事件)。
使用以下方法实现等待指定时间:Thread.Sleep.
不要使用BackgroundWorker
,而是启动一个新的Thread
,并手动设置该线程的ThreadPriority
。然后您将能够使用Thread.Sleep
,并且它应该工作得更精确,因为线程的优先级更高。以下是你最终应该得到的:
void Run()
{
// some initialization stuff
new Thread(DoWork1) { Priority = ThreadPriority.AboveNormal }.Start();
new Thread(DoWork2) { Priority = ThreadPriority.Highest }.Start();
}
private void DoWork2()
{
while (action)
{
if (doItAlways)
{
//do important tasks
}
if (task1)
{
//do things
task1 = false;
}
if (task2)
{
//do things
task1 = false;
}
Thread.Sleep(1);
}
}
private void DoWork1()
{
task1 = true;
Thread.Sleep(12000);//call delay class to wait 12 secs
task2 = true;
Thread.Sleep(12000);//call delay class to wait 12 secs
}