Dan*_*Tao 31 .net messagebox nonblocking blocking winforms
我接受了MUG4N对这个问题的回答,我也想回应一些针对它提出的批评.
克里斯夫说:
...您无法直接从后台线程进行UI调用.
这是一个一揽子声明,并非100%正确.我只想指出一些事实:
实际上,你可以使UI呼吁所有你想要的,如果你设置Control.CheckForIllegalCrossThreadCalls = false."确认!" 我听你说."不要永远做!" 是的,是的 - 但为什么呢?答案:因为有时这会破坏记忆.
中的控件类System.Windows.Forms不是编写为线程安全的,因此有时从后台线程更新它们可能会破坏内存.但是,如果这种情况有时只发生而且并非总是如此,那么这告诉我的不是UI代码本身的调用,而是可能导致异常的UI代码的潜在不安全冲突.
为了强调第1点,请考虑以下事项:从后台线程调用UI代码的"安全"方法是使用Control.Invokeor Control.BeginInvoke,对吗?但这是一个UI调用 ; 如果我们从非GUI线程更新GUI,那只是我们应该进行的 UI调用.我的意思是,显然,它不是简单地Control从外部线程调用对象的"任何"方法,这将导致混乱(如果是这种情况,那么我们甚至无法调用Invoke,我们将被完全卡住) .同样,它是单独的UI调用的潜在冲突,它们不能同时安全地发生,这将证明具有破坏性.
牢记以上两点,请问自己:为什么MessageBox.Show从非GUI线程调用会不安全?Form创建并显示完全独立的内容; 它的属性不以任何方式与任何其他现有GUI对象交互; 事实上,它不能以任何方式在任何地方访问,除了一个:来自调用线程,它访问其属性(并且只通过方法的返回值).DialogResultShow
继续前进.康拉德·阿尔布雷希特说:
...鉴于断言Show()在Dan的ref'd主题中设置了自己的消息泵,(这没有证实,但我不能反驳)......
这是一个完全公平的观点(尽管我个人非常尊重贾里德帕尔,我通常不会怀疑他说的是什么).无论如何,MessageBox.Show通过Reflector查看方法会显示以下片段:
Application.BeginModalMessageLoop();
try
{
result = Win32ToDialogResult(SafeNativeMethods.MessageBox(new HandleRef(owner, zero), text, caption, type));
}
finally
{
Application.EndModalMessageLoop();
UnsafeNativeMethods.ThemingScope.Deactivate(userCookie);
}
Run Code Online (Sandbox Code Playgroud)
进一步了解该Application.BeginModalMessageLoop方法揭示了这一点:
ThreadContext.FromCurrent().BeginModalMessageLoop(null);
Run Code Online (Sandbox Code Playgroud)
而这ThreadContext.FromCurrent反过来:
// [Reflector shows that currentThreadContext is a ThreadStatic member. -Dan]
if (currentThreadContext == null)
{
currentThreadContext = new Application.ThreadContext();
}
return currentThreadContext;
Run Code Online (Sandbox Code Playgroud)
我对这些较低级别的Windows构造知之甚少,无法完全理解这段代码,但在我看来,这似乎是Jared在我的旧评论中引用的答案中的确切证据(对于好奇的读者:MessageBox. Show()自动编组到UI线程?).
是的.我完全同意MUG4N的意见.
(如果有人能够令人信服地说我在这里仍然错了,请说出来.虽然我觉得我为什么相信MUG4N是正确的,但我显然不是100%肯定的.)
通常,您只是想通知用户发生了某些事情,但实际上并不需要他们提供任何输入.在这个常见的场景中,我有时看到这样的代码:
MessageBox.Show("Something has occurred", "Something", MessageBoxButtons.OK);
Run Code Online (Sandbox Code Playgroud)
众所周知,这段代码只会弹出一个弹出窗口,只显示一个OK按钮.现在就是这样的事情:这个代码块(UI线程).但在绝大多数情况下,在我看来,如果你只有一个OK按钮,那么很少需要阻止.(阻止的目的通常是从用户那里接收一些输入吗?如果用户唯一的选择是"OK",在这种典型情况下,是不是阻止相当无意义?)
显然,我可以编写我自己的小形式,基本上完全做什么MessageBox.Show,除了它不返回任何内容(否DialogResult)并且不会阻止.但我只是想知道这样的事情是否已经存在,我不知道.
| 归档时间: |
|
| 查看次数: |
15617 次 |
| 最近记录: |