C#Winform ProgressBar和BackgroundWorker
我有以下问题: 我有一张名为MainForm的表格。我需要在这张表格上做一个长时间的手术 当这个长操作进行时,我需要在MainForm的顶部显示另一个名为ProgressForm的 ProgressForm包含一个进度条,在执行长操作时需要更新该进度条 长时间操作完成后,ProgressForm应自动关闭 我编写了以下代码:C#Winform ProgressBar和BackgroundWorker,c#,winforms,progress-bar,backgroundworker,C#,Winforms,Progress Bar,Backgroundworker,我有以下问题: 我有一张名为MainForm的表格。我需要在这张表格上做一个长时间的手术 当这个长操作进行时,我需要在MainForm的顶部显示另一个名为ProgressForm的 ProgressForm包含一个进度条,在执行长操作时需要更新该进度条 长时间操作完成后,ProgressForm应自动关闭 我编写了以下代码: using System; using System.Collections.Generic; using System.Text; using System.Window
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ClassLibrary
{
public class MyClass
{
public static string LongOperation()
{
Thread.Sleep(new TimeSpan(0,0,30));
return "HelloWorld";
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace BackgroungWorker__HelloWorld
{
public partial class ProgressForm : Form
{
public ProgressForm()
{
InitializeComponent();
}
public ProgressBar ProgressBar
{
get { return this.progressBar1; }
set { this.progressBar1 = value; }
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ClassLibrary;
namespace BackgroungWorker__HelloWorld
{
public partial class MainForm : Form
{
ProgressForm f = new ProgressForm();
public MainForm()
{
InitializeComponent();
}
int count = 0;
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (f != null)
{
f.ProgressBar.Value = e.ProgressPercentage;
}
++count;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("The task has been cancelled");
}
else if (e.Error != null)
{
MessageBox.Show("Error. Details: " + (e.Error as Exception).ToString());
}
else
{
MessageBox.Show("The task has been completed. Results: " + e.Result.ToString());
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (f == null)
{
f = new ProgressForm();
}
f.ShowDialog();
//backgroundWorker1.ReportProgress(100);
MyClass.LongOperation();
f.Close();
}
private void btnStart_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void btnCancel_Click(object sender, EventArgs e)
{
backgroundWorker1.CancelAsync();
this.Close();
}
}
}
我找不到更新progressBar
的方法
我应该将backgroundWorker1.ReportProgress()
放在哪里?我应该如何称呼它
我不能在
MyClass
中做任何更改,因为我不知道会发生什么,也不知道在我的应用程序的这一层中完成操作需要多长时间
有人能帮我吗?一个问题是你睡了30秒。通常,您会在长时间运行的任务中的不同点调用
ReportProgress
。因此,为了演示这一点,您可能希望将代码更改为睡眠1秒,但每次睡眠结束时都要调用30次ReportProgress
另一个问题是,您正在从后台线程显示
ProgressForm
。您应该在UI线程中启动它,但将后台工作人员的ProgressChanged
事件挂接到它。然后,当后台工作人员报告进度时,进度表将被更新。ReportProgress是您必须在“工作”方法中调用的方法。
此方法将引发“ProgressChanged”事件
在表单中,可以将eventhandler附加到ProgressChanged事件。在该eventhandler中,您可以更改progressbar的位置。
您还可以将eventhandler附加到RunWorkerCompleted事件,在该eventhandler中,您可以关闭包含progressbar的表单。应该注意,您需要设置
backgroundWorker1.WorkerReportsProgress = true;
如果希望后台工作程序引发ProgressChanged事件,则
backgroundWorker1.WorkerSupportsCancellation = true;
如果您希望能够取消工作线程
正如其他人所说,在UI线程中运行f.ShowDialog(),并使用ProgressChanged更新ProgressWindow
要使ProgressForm自动关闭,请在backgroundWorker1_RunWorkerCompleted中调用f.close();这意味着长时间的操作已经完成,我们可以关闭窗口。这里需要的不是将整个主窗体传递给类,而是只传递BackgroundWorker的实例!您需要将发件人强制转换为后台工作人员,如下所示:
private void bgWorker_DoWork(object sender DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event
BackgroundWorker worker = sender as BackgroundWorker;
// And now you just send worker to whatever class you need like so:
bgArgs args = e.Argument as bgArgs;
MyClass objMyClass = new MyClass();
MyClass.MyMethod(strValue, args.Option, worker);
// Do something based on return value.
}
然后在MyClass.MyMethod()
中,您可以进行进度计算,只需启动worker.ReportProgress(int percentage)
事件即可更新主UI表单上的进度条或其他内容
这应该是完美的
查看这篇MSDN文章以了解更多详细信息,请参阅他们的Fibonacci示例,这是因为CalculateBonacci
是一个向主窗体的UI发送更新的自定义类
有关更多详细信息,请参阅。我不能对MyClass进行任何更改。因为,我不知道在我的应用程序的这一层会发生什么。那么你就不能准确地报告进度了。我的意思是你可以在
ProgressForm
中添加一个计时器,使进度条每秒递增一次,但这只会产生错觉。如果你无法了解实际进度,那么进度条有多有用?我想这是一个通用的解决方案。请再次阅读问题。从UI线程调用ProgressWindow有什么好处?