线程在 BackgroundWorker 中休眠
Thread sleeping in a BackgroundWorker
我编写了一个简单的应用程序,使用 BackgroundWorker 将 100000 行 "Hello World" 添加到列表中。
下面是我的 backgroundworker 在单独线程中执行的工作代码:
private void BgWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
int min = 0;
foreach (var hw in hwList)
{
//new ManualResetEvent(false).WaitOne(1);
Thread.Sleep(1);
int progress = Convert.ToInt32((Double)min / hwList.Count * 100);
min++;
bgWorker.ReportProgress(progress);
}
}
// Updating the progress
private void BgWorkerOnProgressChanged(object sender, ProgressChangedEventArgs progressChangedEventArgs)
{
ProgressBar.Value = progressChangedEventArgs.ProgressPercentage;
}
一切正常,除了如果我删除 Thread.Sleep(1) BackgroundWorker 不报告进步了。 (我想这需要一些时间)。将线程挂起 1 毫秒实际上会使 BackgroundWorker 报告进度,但它非常慢。
我的问题是,有没有一种方法可以摆脱线程休眠,同时让 BackgroundWorker 正确报告进度?
根据我的理解,暂停 BackgroundWorker 是不可避免的,因为线程需要一些时间来执行任务,但我想知道是否有解决方法。
我遇到了经常报告进度的问题,而且没有理由多次报告相同的进度浪费 cpu 个周期。
private void BgWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
int min = 0;
int oldProgress = 0;
foreach (var hw in hwList)
{
// new ManualResetEvent(false).WaitOne(1);
// Thread.Sleep(1);
int progress = Convert.ToInt32((Double)min / hwList.Count * 100);
min++;
// Only report progress when it changes
if(progress != oldProgress){
bgWorker.ReportProgress(progress);
oldProgress = progress;
}
}
}
// Updating the progress
private void BgWorkerOnProgressChanged(object sender, ProgressChangedEventArgs progressChangedEventArgs)
{
ProgressBar.Value = progressChangedEventArgs.ProgressPercentage;
}
我开发了一个名为 SxProgress 的 class 而不是 BackgroundWorker,它具有非常简单的界面,您可以按以下方式使用它:
int DesiredLinesCount = 100000 ;
List<string> Lines=new List<string>() ;
object[] UserObjects = new object[] { Lines } ;
SxProgress.Execute("Building lines",DesiredLinesCount,true,false,
BuildLines_ExecInThread,UserObjects)) ;
private bool BuildLines_ExecInThread(int ItemIndex,object[] UserObjects)
{
// some sleep to slow down the process (demonstration purpose only)
// if (ItemIndex % 10 ==0) System.Threading.Thread.Sleep(1) ;
List<string> Lines= (List<String>)UserObjects[0] ;
Lines.Add("Hello world") ;
return true ;
}
The SxProgress code is in the last message of this link
另请注意,class 为并行处理提供了相同的简单接口,创建与计算机中的内核一样多的线程,并将项目透明地分派到不同的线程。
will this work for WPF?
Unfortunately no : The class encompasses a form (winforms) with progressbar, labels and stop button.
可能的解决方案:我没试过。
它可以通过从 "Add reference" 对话框窗体(在“.NET”选项卡中)添加到 WPF 项目 2 引用来工作,即"System.Windows.forms" 和 "WindowsFormsIntegration".
然后,在源代码中,添加"using System.Windows.Forms;"
和 "using System.Windows.Forms.Integration;"
我编写了一个简单的应用程序,使用 BackgroundWorker 将 100000 行 "Hello World" 添加到列表中。
下面是我的 backgroundworker 在单独线程中执行的工作代码:
private void BgWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
int min = 0;
foreach (var hw in hwList)
{
//new ManualResetEvent(false).WaitOne(1);
Thread.Sleep(1);
int progress = Convert.ToInt32((Double)min / hwList.Count * 100);
min++;
bgWorker.ReportProgress(progress);
}
}
// Updating the progress
private void BgWorkerOnProgressChanged(object sender, ProgressChangedEventArgs progressChangedEventArgs)
{
ProgressBar.Value = progressChangedEventArgs.ProgressPercentage;
}
一切正常,除了如果我删除 Thread.Sleep(1) BackgroundWorker 不报告进步了。 (我想这需要一些时间)。将线程挂起 1 毫秒实际上会使 BackgroundWorker 报告进度,但它非常慢。
我的问题是,有没有一种方法可以摆脱线程休眠,同时让 BackgroundWorker 正确报告进度?
根据我的理解,暂停 BackgroundWorker 是不可避免的,因为线程需要一些时间来执行任务,但我想知道是否有解决方法。
我遇到了经常报告进度的问题,而且没有理由多次报告相同的进度浪费 cpu 个周期。
private void BgWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
int min = 0;
int oldProgress = 0;
foreach (var hw in hwList)
{
// new ManualResetEvent(false).WaitOne(1);
// Thread.Sleep(1);
int progress = Convert.ToInt32((Double)min / hwList.Count * 100);
min++;
// Only report progress when it changes
if(progress != oldProgress){
bgWorker.ReportProgress(progress);
oldProgress = progress;
}
}
}
// Updating the progress
private void BgWorkerOnProgressChanged(object sender, ProgressChangedEventArgs progressChangedEventArgs)
{
ProgressBar.Value = progressChangedEventArgs.ProgressPercentage;
}
我开发了一个名为 SxProgress 的 class 而不是 BackgroundWorker,它具有非常简单的界面,您可以按以下方式使用它:
int DesiredLinesCount = 100000 ;
List<string> Lines=new List<string>() ;
object[] UserObjects = new object[] { Lines } ;
SxProgress.Execute("Building lines",DesiredLinesCount,true,false,
BuildLines_ExecInThread,UserObjects)) ;
private bool BuildLines_ExecInThread(int ItemIndex,object[] UserObjects)
{
// some sleep to slow down the process (demonstration purpose only)
// if (ItemIndex % 10 ==0) System.Threading.Thread.Sleep(1) ;
List<string> Lines= (List<String>)UserObjects[0] ;
Lines.Add("Hello world") ;
return true ;
}
The SxProgress code is in the last message of this link
另请注意,class 为并行处理提供了相同的简单接口,创建与计算机中的内核一样多的线程,并将项目透明地分派到不同的线程。
will this work for WPF? Unfortunately no : The class encompasses a form (winforms) with progressbar, labels and stop button.
可能的解决方案:我没试过。
它可以通过从 "Add reference" 对话框窗体(在“.NET”选项卡中)添加到 WPF 项目 2 引用来工作,即"System.Windows.forms" 和 "WindowsFormsIntegration".
然后,在源代码中,添加"using System.Windows.Forms;"
和 "using System.Windows.Forms.Integration;"