为啥一个线程会占用所有系统资源而不更新? [复制]
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 技术完全取代。
【讨论】:
以上是关于为啥一个线程会占用所有系统资源而不更新? [复制]的主要内容,如果未能解决你的问题,请参考以下文章