通缉:任何缓解CPU使用率的提示或技巧导致我的应用程序(以及我的整个系统)慢慢爬行。
我有一个应用程序。它调用了几个线程。可能大约5(此刻猜测)。串行端口线程是一个绝对的必需品。我有理由相信该线程是负责任的(例如,所有字节都到达那里,就像它们应该的那样)。
我有几个其他线程观察后台串口处理程序的结果,并响应button1_click
例程等事件中发生的信号量,以便每个人都相处,整个过程顺利运行。基本上,它们只是一个大的循环来检查信号量和分支,如果值这样说。
我最近增加了20个单独的线程;与其他人分开。这些线程将点和线放在20个矩形上(所讨论的设备有20个通道)。我的应用程序存在以记录和绘制它们。
由于添加了这些线程,应用程序立即变得非常缓慢。事实上,整个机器变得非常慢。
所以我停止了应用;机器仍然很慢。所以我退出了Visual Studio;仍然很慢。
次要症状:计算机本身的风扇提高了速度;然后再次提高速度;也许是第三次。我认为这是电源风扇;但无论如何,它是一个粉丝,它继续提高它的速度。 任务经理告诉我这个......
进程选项卡显示大猪是......
myApp.vshost.exe
他对该过程的“描述”是......
vshost32.exe
我使用任务管理器来结束这个过程。
顺便说一下,这不是一个应用程序,Applications
选项卡上没有列出这样的命名应用程序。我只在Processes
标签中看到了它。
在结束myApp.vshost32.exe
进程后,CPU使用率回落,就像这样和谐,就像这样......
CPU使用率几乎垂直增加都与启动20个新线程的行为高度相关。 (点击按钮开始线程;一次点击,zap,CPU 100.)回落到接近零的状态与结束vshost32.exe
的行为完全相关,所以我非常自信(此时至少) vshost32.exe
负责。
当我添加此部分时问题就开始了......
//
//
// Do a bunch of stuff to set up the 20 graphs; had no problem
//
//
for (int i = 0; i < 20; i++)
{ // Start each thread
our20Graphs[i].Begin(); // Start my problems
} // Entire machine now goes 2 MPH
真正的罪魁祸首,在它自己的类中,在它自己的文件中,就在这里......
this.th = new Thread(new ThreadStart(RunTarget));
//
//
// lots of other stuff
//
//
//
public void Begin() ///// A method in the Runtarget
{
this.th.Start();
this.th.IsBackground = true;
}
我见过其他应用程序,类似于我的任务,它可以实时主动地创建一组高度相似的图形,而且不会出现这些极端的CPU使用率,而且速度更快。
目前,我的绘图程序花费了大量时间,数据根本不会出现在屏幕上。不知道这一切是怎么回事。
如果这还不够糟糕(并且它已经糟糕得多,那就是显示停止)这会使整个机器降低到我的应用程序比一个主要应用程序更糟糕的程度,它完全被取消了任何使用的资格完全(机器基本上停止冷)。
那么,为什么20个线程如此可怕地超过系统呢?
我是不是故意让每个线程都睡了一会儿,以便其他线程有机会做他们的东西?
最大的困境:为什么myApp.vshost.exe
即使在我结束应用程序并退出Visual Studio之后仍然继续运行(作为99%的CPU占用率)?
欢迎提出我可能采取的措施,以消除占用大量CPU时间的任何问题。
(添加了编辑,关于社区建议,这是RunTarget)
private void RunTarget()
{
while (proceed)
{
if (!finished)
{
if (!pause)
{
this.screenReady = false;
g.Clear(Color.Black);
// bg.DrawRectangle(new Pen(Brushes.Aqua, 3), new Rectangle(0, 0, 1024, 40));
// oldG.DrawRectangle(new Pen(Brushes.Red, 3), new Rectangle(0, 0, 1024, 40));
if (v_surface)
{
g.DrawImage(beginSurface, new Point(ImagePlace - area.Width, 0));
g.DrawImage(OldSurface, new Point(ImagePlace + 1, 0));
// g.DrawString(ArrayPlacement.ToString(),new Font("Arial",18),Brushes.Blue,new PointF(20,20));
}
else
{
g.DrawImage(OldSurface, new Point(ImagePlace - area.Width, 0));
g.DrawImage(beginSurface, new Point(ImagePlace + 1, 0));
}
this.screenReady = true;
if (ImagePlace % 64 == 0) //// 64 is the size of the array of ints
{
finished = true;
}
if (ImagePlace == area.Width)
{
ImagePlace = 0;
if (v_surface)
{
v_surface = false;
}
else
{
v_surface = true;
}
}
else
{
ImagePlace += 32; //// This is the scrolling increment
}
Draw(); //// This physically puts it on the screen
}
}
}
} //// End of private void RunTarget()
答案 0 :(得分:1)
尝试从项目属性中禁用Visual Studio托管过程。它位于项目属性中 - &gt;调试 - &gt;启用调试器。
答案 1 :(得分:1)
我认为这里有几个问题。第一个,正如其他人提到的那样,你的绘图线程本质上是无限循环,并且看起来你正在通过“忙等待”暂停数据,这将使用每个线程单个核心的100%CPU时间。乘以你正在使用的20个线程,你给系统足够的工作来完全占用20个CPU核心,远远超过你的系统,因此它会使系统上的其他线程挨饿,从而使机器变慢。 / p>
为了使其具有响应性,您需要使用某种等待机制重新实现数据点的暂停。 Thread.Sleep就是这样一种手段,但它可能会导致你的绘图中出现抖动。相反,某种阻塞队列,例如BlockingCollection,它将允许您的消费者线程在没有可用数据时等待(不使用CPU时间),而不是像当前实现那样忙等待。
另一个问题是绘图应该总是在主线程中进行,并且让后台线程进行绘图活动可能会导致其他问题。
答案 2 :(得分:0)
像Dhawalk先生一步一步说道:
在“解决方案资源管理器”中右键单击“您的项目名称”
选择“项目属性”。
从“项目属性”窗口中选择“调试”选项。
如果选中“启用visual studio hosting process”,请取消选中它。
见下图: