在DialogForm上显示MessageBox导致奇怪的UI故障

时间:2013-10-11 18:44:44

标签: c# multithreading winforms devexpress

我的表单上有一个按钮,当点击它时会执行以下操作:

private void btnCheckSVN_Click(object sender, EventArgs e)
{
    wait = new DevExpress.Utils.WaitDialogForm("Fetching File SVN Status", 
                                               "Please Wait");
    wait.AutoSize = true;
    wait.Visible = false;
    bgwSVN.RunWorkerAsync();
    wait.ShowDialog();
}
private void bgwSVN_DoWork(object sender, DoWorkEventArgs e)
{
    e.Result = svn.SvnStatusEventArgsToDataTable(svn.CheckSVN(_localPath));
}

private void bgwSVn_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    DataTable dt = (DataTable)e.Result;
    dt.DefaultView.Sort = "File ASC";
    gdcSVN.DataSource = dt;
    gdcSVNDefaultView.BestFitColumns();
    xtcTabs.SelectedTabPageIndex = 1;
    lblTotalFileCount.Text = dt.Rows.Count.ToString();
    if (dt.Rows.Count == 0)
        XtraMessageBox.Show("No files found.", 
                            "Error",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
    wait.Close();
}

通过这个操作顺序,您(显然)仍然可以看到MessageBox后面的等待对话,我认为它看起来非常草率。

如果我切换IF语句和Close()来电,我的WaitDialogForm一半会因缺少更好的条款而消失。有一个空的矩形,红色的框架和一个巨大的X穿过它,然后在它顶部的MessageBox作为它自己的形式。

这是我第一次搞乱任何类型的多线程或使用BackgroundWorker对象,所以我确定我只是错过了一些非常愚蠢的东西,但我不知道是什么?

我尝试从此事件中完全删除MessageBox,而是执行此操作:

 wait.Close();
 lblTotalFileCount.Text = dt.Rows.Count.ToString();

然后处理标签的TextChanged事件并检查它是否应该显示MessageBox然后......但我仍然用红色框得到相同的结果。

修改;另外,我注意到一个奇怪的事情。在表单加载时,lblTotalFileCount设置为0.当此方法运行并说它找到0个文件时,它会将lblTotalFileCount.Text重新设置为零...哪个会触发TextChanged事件?我知道它已经设置为它已经存在的相同的东西,但它仍然在技术上改变了。我错过了什么,或者事件是否真的检查了那个条件并“跳过”它,如果是这样的话?我不得不将标签设置为空字符串而不是...但是说他们运行应用程序,它被设置为0,提醒他们,他们做了一些更改,再次运行...仍然是0,它不会提醒他们。

编辑2 ;我想也许如果我尝试在TextChanged事件中调用wait.Close(),如我在消息框出现之前的第一个编辑中提到的那样,也许它有用吗?不。同样的问题。然后,如果我第二次单击该按钮,表单崩溃,因为等待已被处理?这是一个形式级别的属性,为什么它会被处置?

编辑3 ;好吧,如果我在TextChanged事件中调用wait.Dispose,我会得到所需的行为。除了它最小化主应用程序,只是向我显示MessageBox,除非它背后没有任何东西。儿子......

1 个答案:

答案 0 :(得分:0)

对Windows窗体控件进行线程安全调用。要从另一个线程修改winform或控件(BackgroundWorker这样做),您应该从主线程进行此调用。在这个问题中,您有答案:How to update the GUI from another thread in C#?