1

需要:任何减轻 CPU 使用率的提示或技巧,这会导致我的应用程序(以及因此,我的整个系统)缓慢爬行。

我有一个应用程序。它调用几个线程。大概5个左右(目前猜测)。串行端口线程是绝对必要的。我有理由相信该线程正在负责任地行事(例如,所有字节都到达那里,就像他们应该的那样)。

我有几个其他线程来观察后台串行端口处理程序的结果,并响应button1_click例程等中发生的信号量,以便每个人都相处融洽,整个事情运行顺利。基本上,它们只是检查信号量和分支的大while循环,如果值这样的话。

我最近添加了 20 个额外的单独线程;与其他人分开。这些线程将点和线放在 20 个矩形上(有问题的设备有 20 个通道)。我的应用程序的存在是为了记录和绘制它们。

由于添加了这些线程,应用程序立即变得非常慢。事实上,整个机器变得非常缓慢。

所以我停止了应用程序;机器仍然很慢。所以我退出了 Visual Studio;还是很慢。

次要症状:电脑本身的风扇转速加快;然后又加快了速度;也许第三次。我认为是电源风扇;但无论如何,它是一个风扇,它继续增加它的速度。任务管理器给我看了这个...

任务管理器性能 进程选项卡显示大猪是...

myApp.vshost.exe

他对那个过程的“描述”是……

vshost32.exe

我使用任务管理器结束该过程。

顺便说一句,这不是一个应用程序,Applications标签上没有列出这样的命名应用程序。我只在Processes标签中看到它。

进程结束后myApp.vshost32.exe,CPU使用率又回落了,就像和谐一样,像这样……

结束 vshost32.exe 后的任务管理器 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 使用率的极限,而且速度更快。

目前,我的绘图程序花费了太多时间,以至于数据根本不会出现在屏幕上。不知道这一切是怎么回事。

如果这还不够糟糕(而且还不够糟糕,那就是表演停止者),这会使整个机器减慢到我的应用程序比 prima donna 应用程序更糟糕的地步,它完全没有资格使用任何用途(机器基本上停止冷却)。

那么,为什么 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()
4

3 回答 3

1

在此处输入图像描述

尝试从项目属性中禁用 Visual Studio 托管进程。它在项目属性--> 调试--> 启用调试器中。

于 2013-01-15T21:00:01.697 回答
1

我认为这里有几个问题。首先,正如其他人所提到的,您的绘图线程本质上是无限循环,并且您似乎正在通过“忙等待”暂停数据,这将使用每个线程单个核心的 100% CPU 时间。将其乘以您正在使用的 20 个线程,您为系统提供了足够的工作来完全占用 20 个 CPU 内核,远远超过您的系统,因此它使系统上的其他线程处于饥饿状态,从而使机器慢得爬行。

我命令它响应,您需要使用某种等待机制重新实现数据点的暂停。Thread.Sleep 就是这样一种方法,但它可能会导致您的绘图出现抖动。取而代之的是某种阻塞队列,例如 BlockingCollection,它允许您的消费者线程在没有可用数据时等待(不使用 CPU 时间),而不是像您当前的实现那样忙于等待。

另一个问题是绘图应该始终发生在主线程中,而让后台线程进行绘图活动可能会导致其他问题。

于 2013-01-16T18:16:18.353 回答
0

就像 Dhawalk 先生一步一步说的:

  1. 在“解决方案资源管理器”中,右键单击“您的项目名称”

  2. 选择“项目属性”。

  3. 从“项目属性”窗口中选择“调试”选项。

  4. 如果选中“启用视觉工作室托管过程”:取消选中它。

请参见下图:

在此处输入图像描述

于 2014-02-01T23:02:49.977 回答