C# 我必须调用()才能从线程显示对话框或MessageBox吗?
我正在工作线程中执行代码。有时,我需要显示一个对话框或消息 我一直在玩代码,似乎只有当我将C# 我必须调用()才能从线程显示对话框或MessageBox吗?,c#,.net,winforms,multithreading,invoke,C#,.net,Winforms,Multithreading,Invoke,我正在工作线程中执行代码。有时,我需要显示一个对话框或消息 我一直在玩代码,似乎只有当我将iwin32窗口传递到对话框时才需要调用Invoke。否则就行了 我的问题有两个: 我必须用Invoke调用吗 如果我在没有调用的情况下显示对话框或消息框,会有什么风险 提前感谢如果您没有指定消息框的所有者它会工作,因为它不依赖表单UI线程。 我认为,如果您不知道显示为特定表单的对话框,则可以不使用Invoke调用它 编辑:要测试它,以下代码只需创建一个新线程并显示消息框,其中在UI线程创建第二条消息的同时
iwin32窗口
传递到对话框时才需要调用Invoke
。否则就行了
我的问题有两个:
提前感谢如果您没有指定
消息框的所有者
它会工作,因为它不依赖表单UI线程。我认为,如果您不知道显示为特定表单的对话框,则可以不使用
Invoke
调用它
编辑:要测试它,以下代码只需创建一个新线程并显示消息框,其中在UI线程创建第二条消息的同时指定所有者作为表单,这两条消息都会毫无问题地显示:
private void button1_Click(object sender, EventArgs e)
{
new Thread(() =>
{
MessageBox.Show("Hello There!");
}) { IsBackground = true }.Start();
Thread.Sleep(1000);
if (MessageBox.Show(this, "Hi", "Jalal", MessageBoxButtons.YesNo) ==
System.Windows.Forms.DialogResult.Yes)
{
return;
}
}
当我需要与主线程中从另一个线程创建的一些控件交互时,我使用BackgroundWorker。它有一个名为OnProgressChange的事件。因此,maeby尝试在主线程中创建此BackgroundWorker对象,在DoWork方法中只触发此事件,然后附加到它的方法将在主线程中执行,这样您就可以访问所有控件。这在Winforms中有点缺陷。它在句柄属性getter中包含诊断代码,用于验证该属性是否与创建句柄的线程在同一线程中使用。虽然对诊断线程错误非常有用,但这并不总是合适的。这里就是这样一种情况,Windows实际上并不要求窗口的父线程属于同一线程 您可以通过pinvoking SetParent()或暂时禁用Control.CheckForIllegalCrossThreadCalls检查来解决此问题。或者使用Control.Invoke(),这是最好的方法。不要通过不指定所有者来解决此问题。由于缺少其他窗口,对话框的所有者是桌面窗口。它将与拥有桌面的其他窗口没有Z顺序关系。这将使对话框偶尔消失在另一个窗口后面,用户完全无法发现
不过还有一个更大的问题,在线程上显示对话框是一个令人讨厌的可用性问题。在用户使用您的程序时,将窗口推到用户的脸上是一个全面的坏主意。当她忙于点击和打字时,不知道会发生什么。她无意中在看不见的情况下关闭了对话,这是一个真正的危险。不要这样做。如果主线程决定抛出一个模式对话框,会发生什么情况?@David:如果太多线程试图使用
调用
显示对话框,最后一个线程将等待第一个对话框返回。@Jalal不,不会。后台线程运行自己的模式消息循环来处理该对话框。@David:No它不会。后台线程运行自己的模式消息循环来处理对话框。
在每个线程中使用调用时
,它们都在UI线程中执行代码。@Jalal Yes,在使用调用时。但问题是当调用未被调用且模式对话框消息循环在后台线程上运行时会发生什么。+1,我同意他不应该这样做,我只是在回答问题。@Jalal-是的,对不起。这是一个值得一提的陷阱。@HansPassant的“Windows实际上并不要求窗口的父线程属于同一线程”。我可以将所有者传递给MessageBox。从非UI线程显示方法,而不必担心?所以,在一些后台线程中,我做了MessageBox.Show(someForm,…)
,这样可以吗?或者我需要测试调用所需的?显示消息框的代码没有绑定到UI组件/表单。。。