【问题标题】:BackgroundWorker is called twice?BackgroundWorker 被调用两次?
【发布时间】:2017-01-19 15:32:21
【问题描述】:

我的后台工作人员有问题,因此它被调用了两次,增加了我的长例程的执行时间,我手动创建了后台工作人员,所以 DoWork 没有机会在 InitializeComponent() 方法中初始化, 任何帮助表示赞赏。

这是我的代码:

namespace formStudent2
{
    public partial class formStudent2 : Form
    {
        private BackgroundWorker backgroundWorker1 = new BackgroundWorker();
        private ProgressBar progressBar1 = new ProgressBar();
        private Label label1 = new Label();

        public formStudent2()
        {
            InitializeComponent();
        }
        ...

        private void btnExportCsv_Click(object sender, EventArgs e)
        {
            // Path output file CSV
            string pathFile = @"D:\DataTest\ListStudent.csv";

            int filesCount = 3;

            // Check if the backgroundWorker is already busy running the asynchronous operation
            if (!backgroundWorker1.IsBusy)
            {
                btnExportCsv.Enabled = false;
                // This method will start the execution asynchronously in the background
                backgroundWorker1.RunWorkerAsync();
            }
            else
            {
                label1.Text = "Busy processing, please wait...";
            }

            /**
             * Display dialog Progress Bar : Exporting data...
             */
            Form form = new Form();
            form.Text = "Exporting data...";
            form.ClientSize = new Size(376, 100);
            form.FormBorderStyle = FormBorderStyle.FixedSingle;
            form.ShowIcon = false;
            form.ControlBox = false;
            form.MaximizeBox = false;
            form.MinimizeBox = false;
            form.StartPosition = FormStartPosition.CenterScreen;

            label1.AutoSize = true;
            label1.Location = new System.Drawing.Point(17, 25);
            label1.Name = "lblPercent";
            label1.Size = new System.Drawing.Size(102, 15);
            label1.TabIndex = 1;
            label1.Text = "0% Completed";
            form.Controls.Add(label1);

            Button btnCancel = new Button();
            btnCancel.Location = new System.Drawing.Point(268, 19);
            btnCancel.Name = "btnCancel";
            btnCancel.Size = new System.Drawing.Size(99, 27);
            btnCancel.TabIndex = 3;
            btnCancel.Text = "Cancel";
            btnCancel.UseVisualStyleBackColor = true;
            btnCancel.Click += (senderq, eq) =>
            {
                if (backgroundWorker1.IsBusy)
                {
                    // Cancel the asynchronous operation id still in progress
                    backgroundWorker1.CancelAsync();
                }
                else
                {
                    form.Close();
                }
            };
            form.Controls.Add(btnCancel);


            progressBar1.Location = new System.Drawing.Point(17, 61);
            progressBar1.Name = "progressBar1";
            progressBar1.Size = new System.Drawing.Size(350, 27);
            form.Controls.Add(progressBar1);


            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
            backgroundWorker1.DoWork += (senderq, eq) =>
            {
                for (int i = 0; i < filesCount; i++)
                {
                    /**
                     * Export to file CSV
                     */
                    ExportFileCsv(pathFile, listStudent);

                    int percentage = (i + 1) * 100 / filesCount;
                    backgroundWorker1.ReportProgress(percentage);

                    // Set cancellation to pending
                    if (backgroundWorker1.CancellationPending)
                    {
                        // Execute cancellation
                        eq.Cancel = true;
                        backgroundWorker1.ReportProgress(0);
                        return;
                    }
                }
            };

            backgroundWorker1.ProgressChanged += (senderq, eq) =>
            {
                // This is updated from doWork. Its where GUI components are update,
                // receives updates after 100ms
                progressBar1.Value = eq.ProgressPercentage;
                label1.Text = eq.ProgressPercentage.ToString() + "% Completed";
            };

            backgroundWorker1.RunWorkerCompleted += (senderq, eq) =>
            {
                // Called when the heavy operation in background is over.
                // Can also accept GUI components
                if (eq.Cancelled)
                {
                    label1.Text = "Processing cancelled.";
                }
                else if (eq.Error != null)
                {
                    label1.Text = eq.Error.Message;
                }
                else
                {
                    btnExportCsv.Enabled = true;
                    MessageBox.Show("Export Finished!");
                    form.Close();
                }
            };

            form.ShowDialog();
        }
    }
}

【问题讨论】:

  • 我不知道它是否会改变一些东西,但你应该把backgroundWorker1.RunWorkerAsync();移到form.ShowDialog();之前。在分配任务之前启动 BackgroundWorker 是不合逻辑的。 MSDN 有一个很好的例子:msdn.microsoft.com/fr-fr/library/cc221403(v=vs.95).aspx
  • 哦,好的。谢谢你。我会参考MSDN
  • 绝对如@gobes所说,确保在执行runworkerasync()之前先添加backgroundworker事件
  • 谢谢,我在想:)
  • 是的,它运行良好。 (y)

标签: c# progress-bar backgroundworker


【解决方案1】:

worker 的运行状态不是静态的。它依赖于一个新的后台工作者的实例。尝试使其共享。

下面是一些伪代码(我是一个 java 人,以前从未用 C# 编程过):

public partial class formStudent {

   boolean workerRunningStatus = false;

    private void btnExportCsv_Click(object sender, EventArgs e)
    {
        // Path output file CSV
        string pathFile = @"D:\DataTest\ListStudent.csv";

        int filesCount = 3;

        // Check if the backgroundWorker is already busy running the asynchronous operation
        if (!workerRunning)
        {
            btnExportCsv.Enabled = false;
            // This method will start the execution asynchronously in the background
            backgroundWorker1.RunWorkerAsync();
        }
        else
        {
            workerRunningStatus = true;
            //then exit
            return;
        }
        //Continue with the remaining logic
     }

}

这只是让工作人员的单个实例运行。或者看看如何在 C# 中使用单例模式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 2012-05-05
    • 2014-02-04
    • 2016-12-13
    • 2016-01-30
    相关资源
    最近更新 更多