C# 未按顺序发生的事件

C# 未按顺序发生的事件,c#,winforms,backgroundworker,C#,Winforms,Backgroundworker,我正在用C#创建一个WinForms应用程序。当我点击一个按钮时,一个特定的事件流应该会发生: 点击按钮 显示标签1 显示标签2 调用函数解析用户之前输入的字符串(这可能需要一段时间,具体取决于字符串) 显示listBox1和progressBar1 backgroundWorker1.RunWorkerAsync backgroundWorker1_DoWork()执行x次操作并每次报告进度 backgroundWorker1_ProgressChanged()更新progressBar1并

我正在用C#创建一个WinForms应用程序。当我点击一个按钮时,一个特定的事件流应该会发生:

  • 点击按钮
  • 显示标签1
  • 显示标签2
  • 调用函数解析用户之前输入的字符串(这可能需要一段时间,具体取决于字符串)
  • 显示listBox1和progressBar1
  • backgroundWorker1.RunWorkerAsync
  • backgroundWorker1_DoWork()执行x次操作并每次报告进度
  • backgroundWorker1_ProgressChanged()更新progressBar1并向listBox1添加一项
  • backgroundWorker1\u RunWorkCompleted()显示一个消息框,显示“完成”
但事实并非如此。当我跟踪代码并查看表单时,它有几个问题

  • 在解析完成之前,label1和label2实际上不会出现
  • progressBar1有时仅在调用ProgressChanged时更新。其他时候,它会等到“完成”后打印并立即更新
  • 每次调用progressChange()时,listBox1上的垂直滚动条都会变小,这样我就可以知道正在添加项目,但项目的文本在打印“完成”后才会显示
  • 我是新使用backgroundWorker的,所以我可能只是不明白它应该如何工作。但是我一点也不明白为什么延迟展示标签。当我跟踪代码时,没有错误,并且这些行似乎是按照正确的顺序执行的

    有人知道是什么导致了这些问题吗?如果有任何帮助或建议,我将不胜感激。我不想发布我的代码,只是因为代码太多了,但是如果有人需要它来更好地理解,只要lmk

    编辑:这是代码

    private void button1_Click(object sender, EventArgs e){
        label1.Show();
        label2.Show();
        String errMsg = parseString();
        if (errMsg == ""){
            listBox1.Items.Clear();
            listBox1.Show();
    
            progressBar1.Maximum = 100;
            progressBar1.Step = 1;
            progressBar1.Value = 0;
            progressBar1.Show();
    
            backgroundWorker1.DoWork += backgroundWorker1_DoWork;
            backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
            backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
    
            if (backgroundWorker1.IsBusy != true)
            {
                backgroundWorker1.RunWorkerAsync();
            }
        }
    }
    
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            backgroundWorker1.ReportProgress(1, "Updating Devices");
            for (int i = 0; i < 100; i++)
            {
                //todo: do stuff
    
                //update progress
                backgroundWorker1.ReportProgress(i, "Device:" + i);
            }
        }
    
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            listBox1.Items.Add(e.UserState);
        }
    
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("DONE");
        }
    
    private void按钮1\u单击(对象发送者,事件参数e){
    label1.Show();
    label2.Show();
    String errMsg=parseString();
    如果(errMsg==“”){
    listBox1.Items.Clear();
    listBox1.Show();
    progressBar1.最大值=100;
    progressBar1.步骤=1;
    progressBar1.值=0;
    progressBar1.Show();
    backgroundWorker1.DoWork+=backgroundWorker1_DoWork;
    backgroundWorker1.ProgressChanged+=backgroundWorker1\u ProgressChanged;
    backgroundWorker1.RunWorkerCompleted+=backgroundWorker1\u RunWorkerCompleted;
    backgroundWorker1.WorkerReportsProgress=true;
    backgroundWorker1.WorkerSupportsScanCellation=true;
    if(backgroundWorker1.IsBusy!=true)
    {
    backgroundWorker1.RunWorkerAsync();
    }
    }
    }
    私有void backgroundWorker1\u DoWork(对象发送方,DoWorkEventArgs e)
    {
    backgroundWorker1.报告进度(1,“更新设备”);
    对于(int i=0;i<100;i++)
    {
    //托多:做事
    //更新进度
    backgroundWorker1.报告进度(i,“设备:+i”);
    }
    }
    私有void backgroundWorker1\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
    {
    progressBar1.值=e.ProgressPercentage;
    listBox1.Items.Add(如UserState);
    }
    私有void backgroundWorker1\u RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
    {
    MessageBox.Show(“完成”);
    }
    
    感谢@HansPassant和@mjwills的评论。他们引导我走上了正确的道路,使这个解决方案成为可能

    最后,我决定做两个后台工作来解决label1和label2直到解析完成后才出现的问题。我使用第一个来做解析,第二个来做“dostuff”部分。在代码中,您将看到我必须使用Invoke来编辑标签,因为该部分现在存在于不同的线程中

    我还意识到,在调用ProgressChanged之前“做一些事情”并不是立即的。我一直在分块开发,尚未实现该代码,但我知道这些操作至少需要3秒钟才能完成(部分原因是涉及ping)。所以现在我在这个循环中加入了一个Sleep(3000)调用来模拟它的实际行为。这解决了由于耗尽所有内存而导致的奇怪progressbar1和listbox1行为

    下面是代码的结果:

    private void button1_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy != true)
            {
                backgroundWorker1.RunWorkerAsync();
            }
        }
    
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            String errMsg = parseString();
            if (errMsg == "")
            {
                if (listBox1.InvokeRequired)
                {
                    listBox1.Invoke(new MethodInvoker(delegate
                    {
                        listBox1.Items.Clear();
                        listBox1.Show();
                    }));
                }
    
                if (progressBar1.InvokeRequired)
                {
                    progressBar1.Invoke(new MethodInvoker(delegate
                    {
                        progressBar1.Maximum = 100;
                        progressBar1.Step = 1;
                        progressBar1.Value = 0;
                        progressBar1.Show();
                    }));
                }
    
                if (backgroundWorker2.IsBusy != true)
                {
                    backgroundWorker2.RunWorkerAsync();
                }
            }
            else
            {
                MessageBox.Show(errMsg);
            }
        }
    
        private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            backgroundWorker2.ReportProgress(1, "Updating Devices");
            for (int i = 0; i < 100; i++)
            {
                System.Threading.Thread.Sleep(3000);
                //do stuff
    
                backgroundWorker2.ReportProgress(i, "Device:" + i);
            }
        }
    
        private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (progressBar1.InvokeRequired)
            {
                progressBar1.Invoke(new MethodInvoker(delegate
                {
                    progressBar1.Value = e.ProgressPercentage;
                }));
            }
            if (listBox1.InvokeRequired)
            {
                listBox1.Invoke(new MethodInvoker(delegate
                {
                    listBox1.Items.Add(e.UserState);
                }));
            }
        }
    
        private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("DONE");
        }
    
    private void按钮1\u单击(对象发送者,事件参数e)
    {
    if(backgroundWorker1.IsBusy!=true)
    {
    backgroundWorker1.RunWorkerAsync();
    }
    }
    私有void backgroundWorker1\u DoWork(对象发送方,DoWorkEventArgs e)
    {
    String errMsg=parseString();
    如果(errMsg==“”)
    {
    如果(listBox1.InvokeRequired)
    {
    listBox1.Invoke(新方法调用器(委托
    {
    listBox1.Items.Clear();
    listBox1.Show();
    }));
    }
    如果(progressBar1.InvokeRequired)
    {
    progressBar1.Invoke(新方法调用器(委托
    {
    progressBar1.最大值=100;
    progressBar1.步骤=1;
    progressBar1.值=0;
    progressBar1.Show();
    }));
    }
    if(backgroundWorker2.IsBusy!=true)
    {
    backgroundWorker2.RunWorkerAsync();
    }
    }
    其他的
    {
    MessageBox.Show(errMsg);
    }
    }
    私有void backgroundWorker2_DoWork(对象发送方,DoWorkEventArgs e)
    {
    backgroundWorker2.报告进度(1,“更新设备”);
    对于(int i=0;i<100;i++)
    {
    系统线程线程睡眠(3000);
    //做事
    backgroundWorker2.报告进度(i,“设备:+i”);
    }
    }
    private void backgroundWorker2\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
    {
    如果(progressBar1.InvokeRequired)
    {
    1.在