C# 后台工作者冻结了 GUI
C# background worker frozen the GUI
我正在尝试使用后台工作程序连续更新文本标签,但是对于 DoWork,如果不使用循环,它只会执行一次,但是如果使用无限循环,它会冻结 GUI,任何想法解决这个?非常感谢!!!我是 C# 的新手,仍在努力学习。
这是我的代码:
主要形式为:
backgroundWorkerX.DoWork += backgroundWorkerX_DoWork;
backgroundWorkerX.ProgressChanged += backgroundWorkerX_ProgressChanged;
backgroundWorkerX.WorkerReportsProgress = true;
backgroundWorkerX.RunWorkerAsync();
然后:
public void backgroundWorkerX_DoWork(object sender, DoWorkEventArgs e)
{
X = -(RSSI_PI1_ST1);
backgroundWorkerX.ReportProgress(X);
}
public void backgroundWorkerX_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label9.Text = e.ProgressPercentage.ToString();
}
public void backgroundWorkerX_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
[...] if no loop used, it will only execute once
这是预期的行为。它将执行预期的操作,然后调用 RunWorkerCompleted
.
[...] but if infinite loop is used, it freezes the GUI.
你的问题中没有循环。所以我会做一个假设,并给你一个有根据的 猜测 它实际上消耗了所有 CPU,因此使 GUI 崩溃。
// I assume that you loop like this somehow.
do
{
X = -(RSSI_PI1_ST1);
backgroundWorkerX.ReportProgress(X);
} while (true);
试着偶尔给"slow it down"加点东西。否则它将尽可能快地 运行 和 运行,因此消耗所有可用的 CPU。请记住,每次您使用 ReportProgress
时,它都会由 GUI 线程呈现。而且这会经常执行并且不会为 GUI 线程留下大量资源来响应其他事情。下面我使用 Thread.Sleep
,这将使线程暂停半秒。但请记住,您只想在后台线程中执行此操作。
do
{
X = -(RSSI_PI1_ST1);
backgroundWorkerX.ReportProgress(X);
Thread.Sleep(500);
} while (true);
我也会考虑换一种方式。如果您确实需要暂停线程,您不妨使用 Timer
. Thread.Sleep
will lock the thread, and may therefore not be what you really want. From this answer:
Process() // method to be called after regular interval in Timer
{
// lengthy process, i.e. data fetching and processing etc.
// here comes the UI update part
Dispatcher.Invoke((Action)delegate() { /* update UI */ });
}
我正在尝试使用后台工作程序连续更新文本标签,但是对于 DoWork,如果不使用循环,它只会执行一次,但是如果使用无限循环,它会冻结 GUI,任何想法解决这个?非常感谢!!!我是 C# 的新手,仍在努力学习。
这是我的代码:
主要形式为:
backgroundWorkerX.DoWork += backgroundWorkerX_DoWork;
backgroundWorkerX.ProgressChanged += backgroundWorkerX_ProgressChanged;
backgroundWorkerX.WorkerReportsProgress = true;
backgroundWorkerX.RunWorkerAsync();
然后:
public void backgroundWorkerX_DoWork(object sender, DoWorkEventArgs e)
{
X = -(RSSI_PI1_ST1);
backgroundWorkerX.ReportProgress(X);
}
public void backgroundWorkerX_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label9.Text = e.ProgressPercentage.ToString();
}
public void backgroundWorkerX_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
[...] if no loop used, it will only execute once
这是预期的行为。它将执行预期的操作,然后调用 RunWorkerCompleted
.
[...] but if infinite loop is used, it freezes the GUI.
你的问题中没有循环。所以我会做一个假设,并给你一个有根据的 猜测 它实际上消耗了所有 CPU,因此使 GUI 崩溃。
// I assume that you loop like this somehow.
do
{
X = -(RSSI_PI1_ST1);
backgroundWorkerX.ReportProgress(X);
} while (true);
试着偶尔给"slow it down"加点东西。否则它将尽可能快地 运行 和 运行,因此消耗所有可用的 CPU。请记住,每次您使用 ReportProgress
时,它都会由 GUI 线程呈现。而且这会经常执行并且不会为 GUI 线程留下大量资源来响应其他事情。下面我使用 Thread.Sleep
,这将使线程暂停半秒。但请记住,您只想在后台线程中执行此操作。
do
{
X = -(RSSI_PI1_ST1);
backgroundWorkerX.ReportProgress(X);
Thread.Sleep(500);
} while (true);
我也会考虑换一种方式。如果您确实需要暂停线程,您不妨使用 Timer
. Thread.Sleep
will lock the thread, and may therefore not be what you really want. From this answer:
Process() // method to be called after regular interval in Timer
{
// lengthy process, i.e. data fetching and processing etc.
// here comes the UI update part
Dispatcher.Invoke((Action)delegate() { /* update UI */ });
}