使用BackgroundWorker时为什么会形成冻结?

时间:2017-02-27 11:04:59

标签: c# winforms backgroundworker freeze

我是C#的新手,我使用的是Windows窗体

我在BackgroundWorker中做了一些工作有问题。

我有2个表单(Form1Form2)和3 User Controls UC1UC2UC3

Form1只有一个显示button Form2的{​​{1}}。

Form2有4 buttonsBtn_ShowUC1Btn_ShowUC2Btn_ShowUC3Button_Close)和3 BackgroundWorkers

我要做的是:当我点击button1中的Form1时,Form2会显示,然后我想显示相关的User control并隐藏当我点击Form2中的任何按钮时休息。例如:点击Btn_ShowUC1 user control1显示并隐藏其余内容,点击Btn_ShowUC2 user control2显示并隐藏其余内容,依此类推。现在在UI中显示和隐藏user controls有时会使Form2冻结,因此我使用BackgroundWorkers来显示/隐藏user control进程。

我正在为每个相关性按钮使用3 BackgroundWorkers,以防一个BackgroundWorker忙于执行显示/隐藏过程。

在Form1中:

    Form2 f2 = new Form2();

    private void button1_Click(object sender, EventArgs e)
    {
        f2.ShowDialog();
    }

在Form2中:

    UserControl CurrentUserControl;
    UserControl1 uc1 = new UserControl1();
    UserControl2 uc2 = new UserControl2();
    UserControl3 uc3 = new UserControl3();

    public Form2()
    {
        InitializeComponent();
        Controls.Add(uc1);
        Controls.Add(uc2);
        Controls.Add(uc3);

    }

  private void Form2_Load(object sender, EventArgs e)
    {

        foreach (Control ctrl in this.Controls)
        {
            if (ctrl is UserControl)
            {
                ctrl.Visible = false;
            }
        }
        uc1.Visible = true;
    }


   private void Btn_ShowUC1_Click(object sender, EventArgs e)
    {
        CurrentUserControl = uc1;
        backgroundWorker1.RunWorkerAsync();

    }
    private void Btn_ShowUC2_Click(object sender, EventArgs e)
    {
        CurrentUserControl = uc2;
        backgroundWorker2.RunWorkerAsync();
    }

    private void Btn_ShowUC3_Click(object sender, EventArgs e)
    {
        CurrentUserControl = uc3;         
        backgroundWorker3.RunWorkerAsync();
    }

  private void Button_Close_Click(object sender, EventArgs e)
    {
       close();
    }

  private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        foreach (Control ctrl in this.Controls)
        {
            if (ctrl is UserControl)
            {
                ctrl.Visible = false;
            }
        }
        CurrentUserControl.Visible = true;
    }

  private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
    {
        foreach (Control ctrl in this.Controls)
        {
            if (ctrl is UserControl)
            {
                ctrl.Visible = false;
            }
        }
        CurrentUserControl.Visible = true;
    }

 private void backgroundWorker3_DoWork(object sender, DoWorkEventArgs e)
    {
        foreach (Control ctrl in this.Controls)
        {
            if (ctrl is UserControl)
            {
                ctrl.Visible = false;
            }
        }
        CurrentUserControl.Visible = true;
    }

Form2加载usercontrol1出现时,当我点击任何任何按钮时,相关的用户控件都显示出来并且每件事情都运行良好。但是,当我关闭form2然后再次打开它并点击任何按钮时,user controls没有显示和Form2冻结,它会抛出错误,说“此backGroundWorker当前正忙,不能同时运行多个任务“ 为什么我有这个错误?我的意思是我正在使用3种不同的backGroundWorkers

请注意,这是我在项目中的所有代码。

任何人都知道如何解决它?我的意思是当我点击任何按钮而不冻结表单时,我想在单独的线程中显示/隐藏用户控件。 我会很高兴听到任何不同的想法。 谢谢

1 个答案:

答案 0 :(得分:1)

错误的情景

虽然这可能是试用BackgroundWorker的好方法,但你使用的却是错误的。 UI线程您通过首先运行应用程序已经使用的那个,应该负责显示/隐藏控件以及任何其他UI相关任务。因此,此BGW实际上是多余的,只需在for-loop事件中执行Button_Click即可。

通过将TrueFalse分配给Visibility属性,您实际上将0从0更改为1。您的机器执行此操作所需的时间和精力是不存在的。 BGWs用于执行长时间运行的任务,单独使用新线程的开销会使设置属性的整个操作浪费资源而完全没必要。

还在吗?

如果您仍然希望这样做,要了解某些内容或其他内容,您需要delegate this work to the UI thread。 发生这种情况是因为您无法从UI线程的任何其他线程访问UI。 这实际上也意味着你的BGW会变得更加浪费资源,因为你实际上创建了一个新线程,无论如何都要在UI线程上做一些事情。 然后,从后台线程,你告诉UI线程(从你开始的地方)无论如何都要执行工作。