【问题标题】:High CPU usage in thread c#线程c#中的高CPU使用率
【发布时间】:2014-04-09 15:57:13
【问题描述】:

嗨,我在运行这个线程时 CPU 使用率很高 (15-16%),它是一个应该保持循环的线程,除非“ssStop”设置为 true(有效),但是,虽然它是运行我打开任务管理器,我看到程序正在使用 15% 的计算机处理能力,一旦线程退出,它就会下降到 1-2%。即使在使用 EventWaitHandle 时,我发现在网上搜索这个问题仍然很高,有谁知道我在这里做错了什么?:

public void Receive()
{
    try
    {              
        bool firstTimeRun = true;
        TcpListener ssTcpListener = new TcpListener(IPAddress.Any, 1500);
        TcpClient tcpReceiver;
        ssTcpListener.Start();
        while (!ssStop)
        {
            //Start listening for connection.
            //Accept any incoming connection requests on port 1500.
            tcpReceiver = new TcpClient();
            if (ssTcpListener.Pending())
            {
                tcpReceiver = ssTcpListener.AcceptTcpClient();
            }
            if (tcpReceiver.Connected)
            {
                //looped for first time; receives whole image.
                if (firstTimeRun)
                {
                    //TCP connected. Receive images from contact
                    NetworkStream receivedNs = new NetworkStream(tcpReceiver.Client);
                    Bitmap image = new Bitmap(receivedNs);
                    receivedImage = image;
                    pboScrnShare.Image = image;
                    receivedNs.Flush();
                    firstTimeRun = false;                            
                }
                //second time or higher looped; receives difference and overlays it.
                else if (!firstTimeRun)
                {
                    NetworkStream receivedNs = new NetworkStream(tcpReceiver.Client);

                    //Put image into picturebox.
                    receivedImage2 = new Bitmap(receivedNs);
                    receivedImage2.MakeTransparent(Color.Black);
                    Bitmap overlayedImage = new Bitmap(receivedImage.Width, receivedImage.Height);

                    using (Graphics gr = Graphics.FromImage(overlayedImage))
                    {
                        gr.DrawImage(receivedImage, new Point(0, 0));
                        gr.DrawImage(receivedImage2, new Point(0, 0));
                    }


                    try
                    {
                        pboScrnShare.Image = overlayedImage;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "pbo second run");
                    }
                    receivedImage2.Dispose();
                    if (this.InvokeRequired) { this.Invoke(new MethodInvoker(delegate() { receivedImage = overlayedImage; })); } else { receivedImage = overlayedImage; }
                    receivedNs.Flush();
                }
                tcpReceiver.Close();
            }
            myEventWaitHandle.WaitOne(10, true);
        }
        ssTcpListener.Stop();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString(), "Invited ReceiveSS()", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

【问题讨论】:

  • 如果您可以在每个循环期间放弃线程 20 毫秒或更长时间,您可以在循环中的某处插入 sleep(1) 以允许其他线程执行。但是,您的代码还有其他问题。由于它是工作代码,请考虑将其发布到 codereview.stackexchange.com,以便获得一些额外的反馈。即使您确实使用了 WaitEventHandle,我认为它不会对您的 CPU 使用率产生任何影响,除非在其他线程中有事情要做。
  • 添加一些仪器来测量时钟滴答声。这将有助于缩小 CPU 使用率的范围。测量系统或函数调用任一侧的时钟滴答声。但请注意,测量刻度也会引入一些开销,所以不要在生产中这样做。测量总比猜测好......

标签: c# multithreading cpu-usage


【解决方案1】:

您正在消耗 CPU 周期,忙于轮询连接。考虑到Pending 大部分时间都返回 false,您的循环会像这样旋转:

while (!ssStop)
{
    tcpReceiver = new TcpClient();
    myEventHandle.WaitOne(10, false);
}

现在,如果 myEventHandle 未设置,那么 WaitOne 中的 10 毫秒延迟将有效地限制执行,但我的猜测是设置了事件,以便 WaitOne 立即返回 true

没有必要轮询连接,因为AcceptTcpClient 将阻塞等待连接。因此,如果您稍微更改一下代码,它应该可以按预期工作:

while (!ssStop)
{
    TcpClient tcpReceiver = ssTcpListener.AcceptTcpClient(); // this blocks
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 2018-09-13
    • 1970-01-01
    相关资源
    最近更新 更多