进度条中的多次迭代C# WinForms

yyhrrdl8  于 2023-05-07  发布在  C#
关注(0)|答案(1)|浏览(132)

我有两个类-形式和功能。出乎意料的是,函数类由函数组成,而且有很多函数(假设有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个完整的迭代。

sy5wg1nm

sy5wg1nm1#

要报告进度,您应该将对计数器的引用作为参数传递。这允许UI和函数共享相同的计数器,同时仍然保持它们分离。它还允许用一个不连接到任何东西的虚拟计数器来调用函数。
典型的方法是使用Progress类。我的偏好是使用0到1范围内的double作为参数,这样调用者就不需要知道实际的迭代次数。Progress<T>将在UI线程上引发其ProgressChanged事件,因此使用起来应该相当简单。

public void First(IProgress<double> progress)
{
    // declaring something, e.g.
    int size = 420;
    for (int i = 0; i < size; i++)
    {
        progress.Report( i / (double)size);
        ...        
    }

    return;
}

在大多数情况下,您可以使用Task.Run运行函数:Task.Run(() => First(progress))。理想情况下,函数应该是“纯”的,以避免线程问题,即根据参数计算值,并且没有副作用。在进行此确定时,有时可以忽略报告进度、取消和记录等副作用。

相关问题