为什么我在不同的线程中打开新窗体后启动位置不同

本文关键字:窗体 位置 新窗体 启动 线程 为什么 | 更新日期: 2023-09-27 18:02:14

我有一个WinForms应用程序,从主表单我打开一个新表单,因为新表单打开从.xml文件读取详细信息,我通过不同的Thread打开这个表单,以避免我的UI卡住(详细信息读取可能需要1-3秒)。当我在不同的Thread中打开此表单时,我的表单出现在我的其他屏幕中(我正在使用双屏幕),尽管StartPosition属性是CenterParent。当我禁用这个新的Thread并从相同的Thread中打开表单时,StartPositionCenterParent

下面是我打开新表单的方式:

       try
        {
            BackgroundWorker backgroundWorker = new BackgroundWorker();
            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.DoWork += new DoWorkEventHandler(
            (s3, e3) =>
            {
                string xmlFile = Path.Combine(
                    Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
                    @"file.xml");
                XmlDocument doc = new XmlDocument();
                doc.Load(xmlFile);
                MyForm frm = new MyForm(doc);
                frm.ShowDialog();
                e3.Result = webmails;
            });
            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
                (s3, e3) =>
                {
                    MyForm frm = (MyForm)e3.Result;                        
                    if (webmails.DialogResult == DialogResult.OK)
                    {
                        // bla bla
                    }
                }
                );
            backgroundWorker.RunWorkerAsync();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Error");
        }

为什么我在不同的线程中打开新窗体后启动位置不同

简单地说:每个窗口堆栈都与单个线程相关。因此,您可能有两个窗口,每个窗口在不同的线程上运行。当你打开一个新窗口或对话框时,它会查看当前线程中窗口堆栈的顶部,并使用顶部作为它的父线程。在您的情况下,frm.ShowDialog();在不同的线程中打开对话框,而不是所有其他窗口,因此它没有可以关联的父线程。

要解决这个问题,要么使用手动调用(如在c#中如何从另一个线程更新GUI ?)或将对话框的打开移动到RunWorkerCompleted事件,这将自动同步到主UI线程上运行。