是否有MessageBox.Show的非阻塞版本(或类似的东西)?

时间:2010-05-14 12:34:39

标签: .net winforms blocking messagebox nonblocking

长时间延迟更新

我接受MUG4N对这个问题的回答,我也想回应针对它提出的一些批评。

ChrisF说:

  

...您无法直接从后台线程进行UI调用。

这是一个一揽子声明,并非100%正确。我只想指出一些事实:

  1. 如果设置Control.CheckForIllegalCrossThreadCalls = false,您实际上可以通过>进行用户界面调用“Ack!”我听到你说。 “不要永远这样做!”是的,是的 - 但是为什么?答案:因为有时这会破坏记忆。

    System.Windows.Forms中的控件类不是编写为线程安全的,因此有时从后台线程更新它们会破坏内存。但如果只有有时发生而不是总是,那么这告诉我的是它不是调用UI代码本身 ,而是可能导致异常的UI代码可能不安全的碰撞

  2. 为了强化第1点,请考虑以下因素:从后台线程调用UI代码的“安全”方法是使用Control.InvokeControl.BeginInvoke来实现,对吧? 是一个用户界面调用;如果我们要从非GUI线程更新GUI,那么它只是我们应该做的 UI调用。我的意思是,显然,它不是简单地从外部线程调用Control对象上的“任何”方法会导致混乱(如果是这种情况,那么我们甚至不能调用{{1而且我们会完全被困住)。同样,这是单独的UI调用的潜在冲突,这些调用不能同时安全地发生,这将证明具有破坏性。

  3. 牢记以上两点,请问自己:为什么从非GUI线程调用Invoke会不安全?创建并显示完全独立的MessageBox.Show;它的属性不以任何方式与任何其他现有GUI对象交互;事实上,它不能以任何方式以任何方式以任何方式访问 ,除了一个:来自调用线程,它访问其Form属性(并且仅通过DialogResult方法的返回值)。

  4. 继续前进。康拉德阿尔布雷希特说:

      

    ...鉴于断言Show()在Dan的ref'd主题中设置了自己的消息泵,(这没有证实,但我不能反驳)......

    这是一个完全公平的观点(虽然我个人非常尊重Jared Par,但我通常不会怀疑怀疑他说的话)。在任何情况下,通过Reflector查看Show方法都可以看到此代码段:

    MessageBox.Show

    进一步了解Application.BeginModalMessageLoop(); try { result = Win32ToDialogResult(SafeNativeMethods.MessageBox(new HandleRef(owner, zero), text, caption, type)); } finally { Application.EndModalMessageLoop(); UnsafeNativeMethods.ThemingScope.Deactivate(userCookie); } 方法可以看出这一点:

    Application.BeginModalMessageLoop

    依次为ThreadContext.FromCurrent().BeginModalMessageLoop(null);

    ThreadContext.FromCurrent

    我对这些较低级别的Windows构造知之甚少,无法完全理解这段代码,但在我看来,这似乎是Jared在我的旧评论中引用的答案的确切证据(对于好奇的读者: Does MessageBox.Show() automatically marshall to the UI Thread?)。

    所以,是的。我完全赞同MUG4N的这一点。

    (如果有人能够令人信服地说我在这里仍然错了,请说出来。虽然我觉得我为什么相信MUG4N是对的,但我显然不是100%肯定的。)< / p>


    原始问题

    通常,您只是想通知用户发生了某些事情,但实际上并不需要来自他们的任何输入。在这种常见情况下,我有时会看到这样的代码:

    // [Reflector shows that currentThreadContext is a ThreadStatic member. -Dan]
    if (currentThreadContext == null)
    {
        currentThreadContext = new Application.ThreadContext();
    }
    return currentThreadContext;
    

    众所周知,此代码只会弹出一个小窗口,只显示确定按钮。现在就是这样的事情:这个代码块(UI线程)。但在绝大多数情况下,在我看来,如果你只有有一个 OK 按钮,那么几乎不需要阻止。 (通常阻止用户接收某些输入的目的不是?如果用户的选择是“OK”,在这种典型的情况下,是不是阻止相当无意义?)

    显然,我可以编写自己的小形式,它基本上完全符合MessageBox.Show("Something has occurred", "Something", MessageBoxButtons.OK); 的作用,除了它不返回任何内容(没有MessageBox.Show)并且不会阻止。但我只是想知道这样的事情是否存在,我不知道。

4 个答案:

答案 0 :(得分:11)

您需要使用多线程来执行此任务,其中一个线程(主线程)将执行处理,另一个线程将用于显示消息框。

答案 1 :(得分:7)

如何在应用中添加NotifyIcon并显示balloon tip呢?缺点是通知会在短时间后消失,但如果用户不需要采取行动,这可能是最好的。

this question还有更多建议。

答案 2 :(得分:2)

我会尝试直接从Win32 API调用MessageBox函数,例如:

using System.Runtime.InteropServices;

[DllImport("User32.dll")]
public static extern int MessageBox(int h, string m, string c, int type);

尝试使用null句柄和APPLMODAL类型。这可能有用。

答案 3 :(得分:0)

这是一个老问题,但是nevertheles ......

1)导入IWshShell('Windows脚本宿主对象模型')

Dim wsh As New IWshRuntimeLibrary.WshShell         wsh.Popup(String.Concat(Me.GetType.FullName,vbCrLf,_                                         Application.ExecutablePath),0.75,“Title”,MessageBoxButtons.OKCancel或MessageBoxIcon.Question)

...延