如何在不同的线程上将所有者窗口传递给MessageBox.Show?

时间:2008-10-12 16:09:53

标签: .net

我想找出Messagebox(ownerWindow,...)。

使用反射器我看到ownerWindow默认为线程的ActiveWindow。

所以我唯一需要ownerWindow参数的时候是从另一个线程调用Show。

然而,当我尝试这个时,我得到一个交叉线程异常。

    private void button1_Click( object sender, EventArgs e ) {
        new Thread( () => MessageBox.Show( this, "Test" ) ).Start();
    }

所以看起来我只需要明确说明所有者窗口,我就不能使用它了!

4 个答案:

答案 0 :(得分:2)

您必须执行BeginInvoke来封送对UI线程的调用。

以下代码是一个简单的示例,您可以如何做到这一点。我没有编译它,所以可能会有错误,但它可能会给你一些指示。

private delegate void ThreadExecuteDelegate(object args);

public void StartThread
{
   Thread thread = new Thread(new ParameterizedThreadStart(ThreadExecute));
   thread.Start((IWin32Window)this);
}

private void ThreadExecute(object args)
{
    if(this.InvokeRequired)
    {
        this.BeginInvoke(new ThreadExecuteDelegate(ThreadExecute), args);
        return;
    }   

    IWin32Window window = (IWin32Window)args;
    MessageBox.Show(window, "Hello world");
}

答案 1 :(得分:1)

正在测试交叉线程的Control.Handle getter。

添加以下代码可修复问题。

   public class Win32Window :IWin32Window {
        IntPtr handle;
        public Win32Window( IWin32Window window ) {
            this.handle = window.Handle;
        }

        IntPtr IWin32Window.Handle {
            get { return handle; }
        }
    }

    private void button1_Click( object sender, EventArgs e ) {
        IWin32Window window = new Win32Window( this );
        new Thread( () => MessageBox.Show( window, "Test" ) ).Start();
    }

答案 2 :(得分:0)

如果您不想在线程中明确地编组调用,请使用BackgroundWorkerReportProgress

答案 3 :(得分:0)

您可能需要查看Win32 Window Hierarchy and Styles以了解所有者和父窗口之间的区别。 ActiveWindows并不总是需要拥有消息框,我已经在应用程序中工作,其中ActiveWindow不一定是MessageBox的所有者。

另外根据win32窗口规则,控件层次结构不能在不同的线程上创建控件,这就是为什么你需要编组对MessageBox.Show的调用。  父窗口的主题。