在多线程函数中的父对话框前面创建子对话框 [英] Make the Child dialog in front of the parent dialog in a multithreaded function

查看:95
本文介绍了在多线程函数中的父对话框前面创建子对话框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在父对话框的一个帖子中创建了一个子对话框,并使用showdialog()方法弹出对话框。现在,当我们点击父对话框时,子对话框会回来。



但是当我们调用showdialog()时,我需要保持父对话框顶部的对话框正常





 m_threadStartTest =  new 主题(StartTest); 
m_threadStartTest.Start();









< pre lang =cs> private void StartTest()
{
MessageBoxForm obj = new MessageBoxForm();
obj.ShowDialog();
}

解决方案

你不能做这些事情。而且,在你的情况下,根本没有任何意义。您需要在UI线程中显示对话框。您用作线程启动的此方法不包含阻塞调用。你必须直接打电话。







然而,我意识到你可以出于某些其他原因使用线程。并且您可以从此已存在的线程触发显示此对话框。在这种情况下,你可以这样做:

  class  MyForm {

< span class =code-comment> // ...
void ShowDialogFromAnyThread(){
System.Action show = new 行动(()= > {
new MessageBoxForm()。ShowDialog();
});
if (InvokeRequired)
Invoke(show);
else
show();
} // ShowDialogFromAnyThread

} // 类MyForm





在这里,我还演示了如何使用本地委托实例重用show调用。

你需要使用调用,而不是 BegingInvoke 。我可以解释一下。



您应该清楚地知道对话框无论如何都会以UI线程显示。







我还想解释 InvokeRequired 的作用。许多人过度使用它,即使它不需要,你也可以使用它。事情很简单:如果你调用像 ShowDialogFromAnyThread 这样的函数并且总是为真,那么这个谓词总是为假来自任何其他线程的调用。该线程的定义很简单:在此上下文中,UI线程只是创建此控件(在本例中为 Form )时的线程。如果调用线程不是那个,则调用总是是必需的。



这样,您也可以通过<$ c跳过检查$ C> InvokeRequired 。如果你总是从其他线程调用这个函数,你不需要检查,知道总是需要调用。



关于调用机制,请参阅我的短文用于线程通信和线程间调用的简单阻塞队列 [ ^ ]。



请同时查看我过去的答案:

Control.Invoke()与Control.BeginInvoke() [ ^ ],

Problem使用Treeview扫描仪和MD5 [ ^ ]。



-SA


你可以在您的孩子ShowDialog方法中传递父表单,如下所示

  private   void  StartTest()
{
if (InvokeRequired)
{
BeginInvoke(< span class =code-keyword> new MethodInvoker(StartTest));
return ;
}
MessageBoxForm obj = new MessageBoxForm();
obj.ShowDialog(parentForm); // 传递您的父表单
}

虽然这样可行对你而言,正如SA在他的解决方案中提到的那样毫无意义。


I created one child dialog in a thread from my parent dialog and Use the showdialog() method to pop up the dialog. Now the child dialog is going back when we click on parent dialog.

But I need stay the dialog on top of the parent dialog as normal when we call showdialog()


m_threadStartTest = new Thread(StartTest);
                m_threadStartTest.Start();





private void StartTest()
       {
           MessageBoxForm obj = new MessageBoxForm();
           obj.ShowDialog();
}

解决方案

You cannot do such things. Moreover, in your case, it makes no sense at all. You need to show dialog in the UI thread. This method you used as a thread start does not contain blocking calls. You had to call it directly.

[EDIT #1]

However, I realize that you can use the thread for some other reasons. And you may trigger showing this dialog from this already existing thread. In this case you can do this:

class MyForm { 

// ...
        void ShowDialogFromAnyThread() {
            System.Action show = new Action(() => {
                new MessageBoxForm().ShowDialog();
            });
            if (InvokeRequired)
                Invoke(show);
            else
                show();
        } //ShowDialogFromAnyThread

} //class MyForm



Here, I also demonstrated how to reuse the show calls with local delegate instance.
You need to use Invoke, not BegingInvoke. I can explain.

You should clearly understand that the dialog will be shown in UI thread anyway.

[EDIT #2]

I also want to explain the role of InvokeRequired. Many excessively use it even it''s not needed, and you might also use it. The thing is very simple: this predicate is always false if you call a function like ShowDialogFromAnyThread and always true in case of the call from any other thread. The thread is defined simply: in this context, the "UI thread" is simply the thread when this control (in this case, Form) was created. If calling thread is some other than that, invoke is always required.

This way, you can also skip the check via InvokeRequired. If you always call this function from some other thread, you don''t need to check, know that invocation is always required.

On the invocation mechanism, please see my short article Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

Please also see my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

—SA


You can pass the parent form in your child ShowDialog method as shown below

private void StartTest()
{
  if (InvokeRequired)
  {
    BeginInvoke(new MethodInvoker(StartTest));
    return;
  }
  MessageBoxForm obj = new MessageBoxForm ();
  obj.ShowDialog(parentForm); //Pass your parent form
}

Though this will work for you, it makes no sense as SA mentioned in his solution.


这篇关于在多线程函数中的父对话框前面创建子对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆