为啥一个线程会占用所有系统资源而不更新? [复制]

Posted

技术标签:

【中文标题】为啥一个线程会占用所有系统资源而不更新? [复制]【英文标题】:Why does a thread take up all system resources and not update? [duplicate]为什么一个线程会占用所有系统资源而不更新? [复制] 【发布时间】:2021-05-16 20:29:18 【问题描述】:

我有一个简单的线程程序,它只是在计数。这个进程应该会占用所有处理器资源,因为它是一个很长的循环。我使用 BackgroundWorker 线程对其进行了编程。所以应该有两个流程。主程序和后台计数器。但是,当程序运行时,应用程序会锁定并且屏幕不会更新。我对其进行了测试,并且正在使用递增的值调用 UpdateStatus。为什么BackgroundWorker会阻止主程序线程中的事件执行?

我意识到我可以包含一个 Application.DoEvents();但这会破坏首先使用线程的目的(允许多个进程相等共享)。为什么BackgroundWorker导致主程序线程停止响应?

    int numTest1 = 0;
    public Form1()
    
        InitializeComponent();
        _worker = new BackgroundWorker();
        _worker.WorkerReportsProgress = true;
        _worker.DoWork += TestCounter;
        _worker.ProgressChanged += UpdateStatus;
        _worker.RunWorkerCompleted += FinalUpdate;
    


    private void btnStart_Click(object sender, EventArgs e)
    
        _worker.RunWorkerAsync();
    

    private void TestCounter(object sender, DoWorkEventArgs e)
    
        for (int loopCount = 0; loopCount < 1000000000; loopCount++)
        
            numTest1 += 1;
            _worker.ReportProgress(0);
        


    private void UpdateStatus(object sender, ProgressChangedEventArgs e)
    
        lblTestUpdate.Text = numTest1.ToString();
    

    private void FinalUpdate(object sender, RunWorkerCompletedEventArgs e)
    
        lblTestUpdate.Text = numTest1.ToString();
        lblTestResult.Text = "Done";
      

【问题讨论】:

您需要做的第一件事是将int numTest1 = 0; 移动到DoWork 处理程序并在方法顶部添加var bgw = sender as BackgroundWorker;。然后看看ReportProgress()是干什么用的。您可以在循环中增加numTest1,然后增加bgw.ReportProgress(loopCount / 1000000000, numTest1);(第一个参数是ProgressPercentage,另一个是UserState)。在循环中,添加Thread.Sleep(1);。之后,e.Result = numTest1;UpdateStatus() 中你将拥有lblTestUpdate.Text = e.UserState.ToString();FinalUpdate()lblTestUpdate.Text = e.Result.ToString(); 好吧,正确的 ProgressPercentage 实际上是 bgw.ReportProgress((int)(((double)numTest1 / 1000000000) * 100), numTest1); 详细信息 :) 【参考方案1】:

_worker.ReportProgress(0) 行用如此大规模的消息淹没了消息循环,以至于消息循环无法及时处理它们。所有其他与 UI 相关的消息都丢失在同一个巨大的队列中,所以一切都卡住了。您应该考虑降低向 UI 线程报告进度的频率。

请注意BackgroundWorker 类在技术上是obsolete。它已被 async/await 技术完全取代。

【讨论】:

以上是关于为啥一个线程会占用所有系统资源而不更新? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

线程池的前世今生

如何查看linux系统的资源占用情况

C# kill线程正常释放资源?

Linux查看系统资源占用

大数据mysql 为啥io过高

Linux中查看系统资源占用情况的命令