C# 在C中,窗体不会使用线程在父窗体的中心打开#

C# 在C中,窗体不会使用线程在父窗体的中心打开#,c#,multithreading,winforms,C#,Multithreading,Winforms,我有一个主窗口表单(不是MDI表单),当我执行某个流程时,在该流程完成之前,我希望显示另一个表单(等待表单) 如果我经常这样做的话 ProgressForm = new FrmProgress(); ProgressForm.StartPosition = FormStartPosition.CenterParent; ProgressForm.ShowDi

我有一个主窗口表单(不是MDI表单),当我执行某个流程时,在该流程完成之前,我希望显示另一个表单(等待表单)

如果我经常这样做的话

   ProgressForm = new FrmProgress();                                                             
   ProgressForm.StartPosition = FormStartPosition.CenterParent;
   ProgressForm.ShowDialog();
            Thread splashThread = new Thread(new ThreadStart(
                delegate
                {
                    ProgressForm = new FrmProgress();
                    Application.Run(ProgressForm);
                }
            ));

            splashThread.SetApartmentState(ApartmentState.STA);
            splashThread.Start();
它可以工作,但在我关闭窗体之前,它会阻塞ShowDialog函数。我知道这里的逻辑

这就是为什么我用类似

Thread splashThread = new Thread(new ThreadStart(
                        delegate
                        {
                            ProgressForm = new FrmProgress();
                            ProgressForm.StartPosition = FormStartPosition.CenterParent;

                            ProgressForm.ShowDialog();
                            //Application.Run(ProgressForm);
                        }
                    ));

            splashThread.SetApartmentState(ApartmentState.STA);
            splashThread.Start();
    //this part is my job

            PackageExtracter packageExtracter = new PackageExtracter();
            packageExtracter.InstallPackage(openDlg.FileName);

            ProgressForm.Invoke(new Action(ProgressForm.Close));
            MessageboxHelper.ShowInfoMessage(Messages.MsgPackageInstalledSuccessfully, Messages.MsgInstallPackageTitle);
            ProgressForm.Dispose();
            ProgressForm = null;
但这次它在第一个监视器中打开了左上角(evne我的主要应用程序在第二个监视器上)

我想将“等待表单”显示为模态,并在我的工作完成时隐藏表单

有什么想法吗?

它就是这样工作的

   ProgressForm = new FrmProgress();                                                             
   ProgressForm.StartPosition = FormStartPosition.CenterParent;
   ProgressForm.ShowDialog();
            Thread splashThread = new Thread(new ThreadStart(
                delegate
                {
                    ProgressForm = new FrmProgress();
                    Application.Run(ProgressForm);
                }
            ));

            splashThread.SetApartmentState(ApartmentState.STA);
            splashThread.Start();
它是这样工作的

   ProgressForm = new FrmProgress();                                                             
   ProgressForm.StartPosition = FormStartPosition.CenterParent;
   ProgressForm.ShowDialog();
            Thread splashThread = new Thread(new ThreadStart(
                delegate
                {
                    ProgressForm = new FrmProgress();
                    Application.Run(ProgressForm);
                }
            ));

            splashThread.SetApartmentState(ApartmentState.STA);
            splashThread.Start();

您的标题提到您希望它显示在另一个表单的中心。看起来您尚未为ProgressForm设置父窗体。您可以通过将父窗体传递到ShowDialog方法中来设置它

ProgressForm.ShowDialog(someParentForm);
但是,如果另一个UI线程拥有someParentForm对象,我不相信这会起作用

--

如果只希望进度位于屏幕中央,则可以使用CenterScreen而不是CenterParent:

   ProgressForm.StartPosition = FormStartPosition.CenterScreen;
   ProgressForm.ShowDialog();

您的标题提到您希望它显示在另一个表单的中心。看起来您尚未为ProgressForm设置父窗体。您可以通过将父窗体传递到ShowDialog方法中来设置它

ProgressForm.ShowDialog(someParentForm);
但是,如果另一个UI线程拥有someParentForm对象,我不相信这会起作用

--

如果只希望进度位于屏幕中央,则可以使用CenterScreen而不是CenterParent:

   ProgressForm.StartPosition = FormStartPosition.CenterScreen;
   ProgressForm.ShowDialog();

好吧,我不认为如果你从另一个线程打开它,
ProgressForm
可以知道它的父对象是谁。如果内存正常,
ShowDialog
具有接受所有者窗口的重载。打开窗体时是否尝试将主窗体的实例传递给该重载?这只是一个想法,我从来不需要这样做。此外,如果在用户可以继续使用你的应用程序之前,不是必须完成的事情,请评估在后台工作的选项
async/await
在这里会有所帮助。s,m是对的,ProgressForm不知道主窗体,因为它在另一个线程中。您最好的选择是在BackgroundWorker中开始您的工作,或者使用其他方法在后台运行它。启动工作线程后,您会将ProgressForm连接到某个事件,报告进度,然后用ShowDialog显示。@s.m.谢谢您的回复。我可以走更长的路,但我不想要。异步似乎不错。我会试试看。你是想让表单如你的问题中定义的那样作为模型(总是在顶部),还是在中间(如你的标题中定义的)?或者您想解决您的splashscreen无法从
ShowDialog
返回的问题吗?@BoeseB,谢谢您的回答。我想是的。。但首先,如果我能用一个简单的线程解决它,它可能会更好。否则我会照你说的做。好吧,如果你从不同的线程打开它,我不认为
ProgressForm
可以知道它的父对象是谁。如果内存正常,
ShowDialog
具有接受所有者窗口的重载。打开窗体时是否尝试将主窗体的实例传递给该重载?这只是一个想法,我从来不需要这样做。此外,如果在用户可以继续使用你的应用程序之前,不是必须完成的事情,请评估在后台工作的选项
async/await
在这里会有所帮助。s,m是对的,ProgressForm不知道主窗体,因为它在另一个线程中。您最好的选择是在BackgroundWorker中开始您的工作,或者使用其他方法在后台运行它。启动工作线程后,您会将ProgressForm连接到某个事件,报告进度,然后用ShowDialog显示。@s.m.谢谢您的回复。我可以走更长的路,但我不想要。异步似乎不错。我会试试看。你是想让表单如你的问题中定义的那样作为模型(总是在顶部),还是在中间(如你的标题中定义的)?或者您想解决您的splashscreen无法从
ShowDialog
返回的问题吗?@BoeseB,谢谢您的回答。我想是的。。但首先,如果我能用一个简单的线程解决它,它可能会更好。否则我就照你说的做