在c#中使用进度条

本文关键字: | 更新日期: 2023-09-27 18:02:28

我想在我的c#应用程序中显示一个进度条。有一个函数,我调用按钮点击在我的应用程序,这是耗时的,它是不可能确定需要多少时间来完成整个过程,因为我正在从Excel表读取数据和存储到数据库和所有的东西。

当我点击按钮时,进度条应该显示正确的状态,当整个过程完成时,我想显示"完成成功"的消息。

 AlertForm alert;
 private void btnImport_Click(object sender, EventArgs e)
 {
 if (backgroundWorker1.IsBusy != true)
                    {
                        // create a new instance of the alert form
                        alert = new AlertForm();
                        // event handler for the Cancel button in AlertForm
                        alert.Canceled += new EventHandler<EventArgs>(buttonCancel_Click);
                        alert.Show();

                        backgroundWorker1.RunWorkerAsync();
                                                   StartConversion(txtPath.Text.Trim(), Path.GetFileName(txtPath.Text.Trim()));
                    }
}
 #region Progress bar EVENTS
    private void buttonStart_Click(object sender, EventArgs e)
    {
        if (backgroundWorker1.IsBusy != true)
        {
            // create a new instance of the alert form
            alert = new AlertForm();
            // event handler for the Cancel button in AlertForm
            alert.Canceled += new EventHandler<EventArgs>(buttonCancel_Click);
            alert.Show();
            // Start the asynchronous operation.
            backgroundWorker1.RunWorkerAsync();
        }
    }
    // This event handler cancels the backgroundworker, fired from Cancel button in AlertForm.
    private void buttonCancel_Click(object sender, EventArgs e)
    {
        if (backgroundWorker1.WorkerSupportsCancellation == true)
        {
            // Cancel the asynchronous operation.
            backgroundWorker1.CancelAsync();
            // Close the AlertForm
            alert.Close();
        }
    }
    // This event handler is where the time-consuming work is done.
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        for (int i = 1; i <= 10; i++)
        {
            if (worker.CancellationPending == true)
            {
                e.Cancel = true;
                break;
            }
            else
            {
                // Perform a time consuming operation and report progress.
                worker.ReportProgress(i * 10);
                System.Threading.Thread.Sleep(500);
            }
        }
    }
    // This event handler updates the progress.
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // Show the progress in main form (GUI)
        labelResult.Text = (e.ProgressPercentage.ToString() + "%");
        // Pass the progress to AlertForm label and progressbar
        alert.Message = "In progress, please wait... " + e.ProgressPercentage.ToString() + "%";
        alert.ProgressValue = e.ProgressPercentage;

    }
    // This event handler deals with the results of the background operation.
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled == true)
        {
            labelResult.Text = "Canceled!";
        }
        else if (e.Error != null)
        {
            labelResult.Text = "Error: " + e.Error.Message;
        }
        else
        {
            labelResult.Text = "Done!";
        }
        // Close the AlertForm
        alert.Close();
    }
    #endregion

AlertForm是我的应用程序中的另一个表单,用于显示进度条StartConversion()方法是调用另一个方法的方法,该方法存在于实际执行耗时任务的类中。

我如何完成这个任务?

在c#中使用进度条

通常使用BackgroundWorker

它运行在一个单独的线程中,并提供工具来实现您的两个需求(更新进度信息,并在操作完成时执行其他操作)。您只需要创建一个BackgroundWorker实例并将其WorkerReportsProgress -属性设置为true

然后只需订阅相应需求的 events:

  1. DoWork -执行实际的长时间运行任务
  2. ProgressChanged -更新进度信息(例如ProgressBar-value)
  3. RunWorkerCompleted -显示成功消息

最后调用RunWorkerAsync -方法,就完成了。

示例代码

var demoWorker = new BackgroundWorker { WorkerReportsProgress = true };
demoWorker.DoWork += (sender, args) =>
            {
                var worker = sender as BackgroundWorker;
                if (sender == null) throw new Exception("Not a BackgroundWorker!");
                foreach (var VARIABLE in COLLECTION)
                {
                    // do your work
                    worker.ReportProgress(progressPercentage); // invokes the workers ProgressChanged-event
                }
            }
demoWorker.ProgressChanged += (sender, args) =>
            {
                this.progressBar.Value = args.ProgressPercentage;
            };    
demoWorker.RunWorkerCompleted += (sender, args) =>
            {
                // invoked when DoWork's eventhandler terminates
                // show message
            };
demoWorker.RunWorkerAsync(); // Invokes the workers DoWork-event

你应该使用后台worker。

想象以下场景:

您有一个大约有1000行要处理的excel文件。对于进度条,可以假设10行是一个百分比。

在backgroundworker中,你让它时不时地与主线程通信,说明已经处理了多少百分比。

backgroundworker有一个事件,可以用来时不时地填充你的进度条:

例如:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        var base = 100;
        var counter = ExcelRows.Count;
        var progressCounter = 0;
        for (int i = 1; i <= ExcelRows.Count; i++)
        {
            if (worker.CancellationPending == true)
            {
                e.Cancel = true;
                break;
            }
            else
            {
                // Perform a time consuming operation and report progress.
                //perform you action
                MyRow.Save();
                //report to the Progressbar
                if(i % counter == 0)
                     worker.ReportProgress(progressCounter++);
            }
        }
    }
    // This event handler updates the progress. 
    private void backgroundWorker1_ProgressChanged(object sender,           ProgressChangedEventArgs e)
    {
        MyProgress.Value = string.Format("{0}/100 %",e.ProgressPercentage);
    }

这样的方法是使用不同的线程使用backgroundworker。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        InitializeBackgroundWorker();
    }
    private bool done = true;
    int percentComplete = 1;
    internal bool ImportData(IList<string> filenames)
    {
        try
        {
            // Long running task around 5 to 10 minutes
            return true;
        }
        catch (Exception ex)
        {
            // returning true to break from th display progress loop
            return true;
        }
    }
    private void InitializeBackgroundWorker()
    {
        backgroundWorker = new BackgroundWorker
        {
            WorkerReportsProgress = true,
            WorkerSupportsCancellation = true
        };
        backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
        backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
        backgroundWorker.ProgressChanged +=new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
    }
    private void button1_Click(System.Object sender,System.EventArgs e)
    {
        //fd is Browse dialog to select files in my case
        if (fd.ShowDialog() == DialogResult.OK)
        {
            var flist = fd.FileNames.ToList();                
            // Disable the Start button until the asynchronous operation is done.
            this.startButton.Enabled = false;
            if (!backgroundWorker.IsBusy)
            {
                this.Cursor = Cursors.WaitCursor;
                backgroundWorker.RunWorkerAsync(flist);
            }
            else
            {
                backgroundWorker.CancelAsync();
            }
        }
    }
    private void DisplayProgress(BackgroundWorker worker)
    {
        try
        {
            percentComplete = 1;
            while (done)
            {
                Thread.Sleep(500);
                // Report progress
                if (percentComplete == 100)
                    percentComplete = 1;
                worker.ReportProgress(++percentComplete);
            }
        }
        catch (Exception e)
        {
        }
    }
    // This event handler is where the actual,
    // potentially time-consuming work is done.
    private void backgroundWorker_DoWork(object sender,DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        if (worker.CancellationPending)
        {
            e.Cancel = true;
        }
        else
        {
            new Thread(() =>
            {
                DisplayProgress(worker);
            }).Start();
            done = ImportData((List<string>) e.Argument);
            worker.ReportProgress(100);
            e.Result = "Converted " + Path.GetFileName(((List<string>) e.Argument)[0]) + " successfully.";
        }
    }
    // This event handler deals with the results of the background operation.
    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // First, handle the case where an exception was thrown.
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
        }
        else if (e.Cancelled)
        {
            // Next, handle the case where the user canceled
            // the operation.
            // Note that due to a race condition in
            // the DoWork event handler, the Cancelled
            // flag may not have been set, even though
            // CancelAsync was called.               
        }
        else
        {
            // Finally, handle the case where the operation succeeded.
            listView.Items.Add(new ListViewItem(Text = e.Result.ToString()));
            this.Cursor = Cursors.Arrow;
        }
        startButton.Text = "Start";
        startButton.Enabled = true;
    }
    // This event handler updates the progress bar.
    private void backgroundWorker_ProgressChanged(object sender,ProgressChangedEventArgs e)
    {
        this.progressBar.Value = e.ProgressPercentage;
    }
}
相关文章:
  • 没有找到相关文章