背景工作者的问题,GUI被绞死

时间:2011-12-05 11:12:47

标签: c# c#-4.0 c#-3.0

我在一个表单下面使用了一个后台工作者,当我点击一个按钮它应该生成一个文档,但是GUI挂起,我不知道为什么会这样做,因为我觉得我正在使用backgroundworker。任何人都可以帮忙吗?

  private void btn_GenerateRevDoc_Click(object sender, EventArgs e)
    {
        DOC_GenerateVersDocBackgroundWorker = new BackgroundWorker();
        DOC_GenerateVersDocBackgroundWorker.WorkerReportsProgress = true;
        DOC_GenerateVersDocBackgroundWorker.WorkerSupportsCancellation = true;

        DOC_GenerateVersDocBackgroundWorker.DoWork += new DoWorkEventHandler(DOC_GenerateVersDocBackgroundWorker_DoWork);
        DOC_GenerateVersDocBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(DOC_GenerateVersDocBackgroundWorker_ProgressChanged);
        DOC_GenerateVersDocBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(DOC_GenerateVersDocBackgroundWorker_RunWorkerCompleted);
        System.Threading.Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
        if (Db.docVersionHistory != null && Db.docVersionHistory.Count > 0)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Title = "Export Review To";
            sfd.Filter = "Word files (*.doc)|*.doc|All files (*.*)|*.*";
            sfd.FilterIndex = 1;
            sfd.FileName = "";

            if (sfd.ShowDialog() == DialogResult.OK)
            {


                if (!DOC_GenerateVersDocBackgroundWorker.IsBusy)
                    DOC_GenerateVersDocBackgroundWorker.RunWorkerAsync(sfd.FileName);
            }
        }
        else
        {
            MessageBox.Show("No Review Records were found!");
        }

    }
    void DOC_GenerateVersDocBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        if (this.InvokeRequired)
        {
            Invoke(new MethodInvoker(delegate
                     {

                         DocumentsNavigator.GenerateWordRevisionHistoryDoc(DOC_GenerateVersDocBackgroundWorker, versionsList, Db, (string)(e.Argument));

                     }));
        }
        else
        {
            DocumentsNavigator.GenerateWordRevisionHistoryDoc(DOC_GenerateVersDocBackgroundWorker, versionsList, Db, (string)(e.Argument));

        }
    }

5 个答案:

答案 0 :(得分:1)

您并不完全了解BackgroundWorker应该如何使用,以及Invoke方法的用途。

Invoke方法导致在UI线程上调用代码。因此,请勿通过DocumentsNavigator.GenerateWordRevisionHistoryDoc传递Invoke方法。 RunWorkerAsync没问题。我不知道versionsListDb是什么类型,但如果它们是UI对象,则可能需要将所需的值复制到新变量中。例如,如果versionsListListBox,则应将所选值复制到新的string[],并将string[]用作方法的参数。

以下是您认为您想要做的事情:

  • 创建新的后台工作程序

  • 初始化您的后台工作人员

  • 停用btn_GenerateRevDoc按钮

  • 显示SaveFileDialog

  • 启动BackgroundWorker(RunWorkerAsync

  • ProgressChanged事件中,如果您正在显示进度条或 什么,你可以更新,这次你必须通过它 通过Invoke方法。

  • RunWorkerCompleted事件中,显示消息框或其他内容, 并再次启用btn_GenerateRevDoc按钮

哦,这行应该绝对删除:

System.Threading.Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;

答案 1 :(得分:0)

在您的后台工作人员中,您再次将所有工作转发到UI线程,这就是您的UI挂起的原因

 if (this.InvokeRequired)
        {
            //this executes the work on UI thread
            Invoke(new MethodInvoker(delegate
                     {

                         DocumentsNavigator.GenerateWordRevisionHistoryDoc(DOC_GenerateVersDocBackgroundWorker, versionsList, Db, (string)(e.Argument));

                     }));
        }
        else
        {
//it will also be executed on UI thread     
   DocumentsNavigator.GenerateWordRevisionHistoryDoc(DOC_GenerateVersDocBackgroundWorker, versionsList, Db, (string)(e.Argument));

        }
    }

答案 2 :(得分:0)

  

当我点击一个按钮时,它应该生成一个文档,但GUI挂起

从您的代码

我可以看到您应该输入文件名并单击确定。是否在某处打开了保存对话框?

尝试在不使用后台工作程序的情况下编写相同的代码。它还挂着吗?此外,观察到条件if (!DOC_GenerateVersDocBackgroundWorker.IsBusy)没有意义,因为每次点击按钮都会创建一个新的背景工作者

答案 3 :(得分:0)

问题是您正在运行在工作线程中挂起GUI但在Invoke方法中执行此操作的代码。

Invoke方法在GUI的线程中运行代码,因此它会挂起。

如果你绝对必须在GUI线程中调用DocumentsNavigator.GenerateWordRevisionHistoryDoc,我就不知道如何在不挂起GUI的情况下进行此调用。

尝试重新考虑您的代码,这样您就不必在Invoke方法中运行BackgroungWorker中的任何代码。

答案 4 :(得分:-1)

你做的事情不安全。

而不是Invoke尝试

if (this.InvokeRequired)         
{             this.BeginInvoke(new MethodInvoker(delegate                      
   {