C#Backgroundworker-在运行代码时显示表单,并在代码完成后关闭

C#Backgroundworker-在运行代码时显示表单,并在代码完成后关闭,c#,backgroundworker,C#,Backgroundworker,我有一个Excel主详细信息导出的方法,可以通过单击按钮来处理。方法在3个单独的线程中运行,以提高性能。我想显示一个通知用户数据处理的表单(不是进度条表单,只是一个包含图像的表单)。使用backgroundworker表单可以在不阻塞UI线程的情况下很好地打开,但在Excel导出方法完成后,我无法在需要时关闭它 第一次尝试: private void Button1_Click(object sender, EventArgs e) { alert = new p

我有一个Excel主详细信息导出的方法,可以通过单击按钮来处理。方法在3个单独的线程中运行,以提高性能。我想显示一个通知用户数据处理的表单(不是进度条表单,只是一个包含图像的表单)。使用backgroundworker表单可以在不阻塞UI线程的情况下很好地打开,但在Excel导出方法完成后,我无法在需要时关闭它

第一次尝试:

  private void Button1_Click(object sender, EventArgs e)
  {
            alert = new process_form();
            alert.ShowDialog();
            bw.DoWork += (s, ea) =>
            {
                // Error: current thread must be set to single thread apartment(STA) mode before OLE calls can be made.

                //Method for Excel export - It runs in async
                ExportData();

                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                GC.WaitForPendingFinalizers();
            };
            bw.RunWorkerCompleted += (s, ea) =>
            {
                //close form
                this.Invoke(new System.Action(() => { alert.Close(); }));
            };
            bw.RunWorkerAsync();
    }
第二次尝试-没有错误,但我无法关闭表单:

  private void Button1_Click(object sender, EventArgs e)
  {
        backgroundWorker1.RunWorkerAsync();

        //Method for Excel export
        ExportData();

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        GC.WaitForPendingFinalizers();
  }

  private void ExportData()
  {
    //...

    //Cancel async just before SaveFileDialog shows
    backgroundWorker1.CancelAsync();

    SaveFileDialog save_export = new SaveFileDialog();
    if (save_export() == DialogResult.OK)
    {
      //...
    }
  }

  private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
  {
            if ((backgroundWorker1.CancellationPending == true))
            {
                alert.Close();
                e.Cancel = true;
            }
            else
            {
                alert = new process_form();
                alert.ShowDialog();
            }
    }

我也尝试过创建一个新线程并从那里打开一个窗体,然后调用Thread.Abort(),但这会产生一些不希望的结果——例如,当process\u窗体关闭时,任何底层窗口都会变成应用程序上方的顶部窗口。所以backgroundworker是我想要的解决方案。

解决了。我放弃了BGW,做了以下事情:

  • 打开表单“处理表单”(“警报”实例)
  • 以异步方式包装ExportData并运行它
  • 在ExportData中,在打开SaveFileDialog之前:

  • 看起来需要在另一个线程中打开SaveFiledialog,在我的例子中,这可能是一个问题。谢谢你的帮助

    通过让BGW创建表单,您很可能会将所有内容都放在后面。而是使窗体包含BGW,并使其从Form.Show事件开始。还可以将表单转换为模式对话框。除了针对Windows窗体+BGW的特殊解决方案之外,您还说您正在使用多线程来提高性能。但多线程只对CPU受限的工作有帮助。你对这种情况有多确定?这听起来像是磁盘绑定(excel的I/O)。您的后台工作人员正在将警报显示为对话框,这意味着在关闭警报之前,表单上的所有处理都将停止。因此,您的dowork将检查其未取消并显示一个对话框。。它不再检查cancellation@Christopher,我想我不太明白你的意思,你能给我举个例子吗?…关于ExportData中的多线程-没有多线程,我的xxport运行缓慢-它不仅从DB中捕获数据,而且还设计Excel工作表来删除数据。@BugFinder,修复为just.show()解决不了我的问题。做我的研究让我做到了,但我不能让它同样工作。@Lucy82好的,那么使用那个链接有什么地方不起作用呢?
    this.Invoke((MethodInvoker)delegate
       {
          alert.Close();
         SaveFileDialog save_export = new SaveFileDialog
         {
          //...
         }
        });