我有两个类-形式和功能。出乎意料的是,函数类由函数组成,而且有很多函数(假设有20个)。它们都使用不同的算法和外部库,但它们都以循环的方式传递进度索引来显示进度。我需要通过这些指标在进度条在我的形式。我倾向于使用Background Worker,但可能我搞错了。问题是我不知道用户会选择多少函数,所以我不能把这些算法放在DoWork事件处理程序中,也不能把它们转移到任何其他类中,它们应该保持不变。
我简化了代码,只留下了两个函数:
class Functions
{
public void First()
{
int progressIndex = 0;
// declaring something, e.g.
int size = 420;
for (int i = 0; i < size; i++)
{
// some operations, finally:
progressIndex++;
form.label1.Text = "Function 1 executing..."; // also, how do I pass this to the label?
}
return;
}
// similar
public void Second()
{
int index = 0;
int gridCount = 86039;
for (int i = 0; i < gridCount; i++)
{
index++;
form.label1.Text = "Function 2 executing...";
return;
}
}
形式:
public partial class Form1 : Form
{
Functions functions;
public Form1()
{
InitializeComponent();
}
private void buttonStart_Click(object sender, EventArgs e)
{
Execute();
label1.Visible = true;
label2.Visible = true;
buttonStop.Visible = true;
buttonStart.Enabled = false;
}
void Execute()
{
if (isFirst)
functions.First();
if (isSecond)
functions.Second();
}
private void buttonStop_Click(object sender, EventArgs e)
{
worker.CancelAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
// ???
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
label2.Text = (e.ProgressPercentage.ToString() + "%");
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
MessageBox.Show("Cancelled");
}
else if (e.Error != null)
{
MessageBox.Show("Error: " + e.Error.Message);
}
else
{
MessageBox.Show("Completed!");
}
}
public bool isFirst
{
get { return checkBox1.Checked; }
set { checkBox1.Checked = value; }
}
public bool isSecond
{
get { return checkBox2.Checked; }
set { checkBox2.Checked = value; }
}
会感激任何帮助,谢谢
我需要我的进度条来显示一个接一个的进度,例如,如果用户选择了20个功能中的3个,它将显示从0到100的3个完整的迭代。
1条答案
按热度按时间sy5wg1nm1#
要报告进度,您应该将对计数器的引用作为参数传递。这允许UI和函数共享相同的计数器,同时仍然保持它们分离。它还允许用一个不连接到任何东西的虚拟计数器来调用函数。
典型的方法是使用Progress类。我的偏好是使用0到1范围内的double作为参数,这样调用者就不需要知道实际的迭代次数。
Progress<T>
将在UI线程上引发其ProgressChanged
事件,因此使用起来应该相当简单。在大多数情况下,您可以使用Task.Run运行函数:
Task.Run(() => First(progress))
。理想情况下,函数应该是“纯”的,以避免线程问题,即根据参数计算值,并且没有副作用。在进行此确定时,有时可以忽略报告进度、取消和记录等副作用。