对于不阻止GUI线程的MessageBox.Show替换的建议?

时间:2021-11-06 17:00:57

a while back I ran across a situation where we needed to display message-boxes to the user for notifications but we could not use MessageBox.Show because it blocks the GUI thread (so nothing on the screen gets updated while the dialog is active). Any suggestions on an alternative?

前段时间我遇到了一个情况,我们需要向用户显示消息框以获取通知,但我们无法使用MessageBox.Show,因为它会阻止GUI线程(因此在对话框处于活动状态时,屏幕上的任何内容都不会更新)。关于替代方案的任何建议?

[I coded an alternative at the time but I don't like it. I'll post it as an answer if nothing better appears though]

[我当时编写了一个替代品,但我不喜欢它。如果没有更好的出现,我会发布它作为答案]

EDIT: the dialog must float on top of the main window; i don't care if it appears in the taskbar or not. More than one dialog may be active at once in certain circumstances.

编辑:对话框必须浮动在主窗口的顶部;我不在乎它是否出现在任务栏中。在某些情况下,可能会同时激活多个对话框。

ADDENDUM: my solution was a base form that provided OK and CANCEL buttons to emit Completed and Cancelled events; OK called a virtual ValidateData for subclass override. The calling form used properties to avoid recreating the form each time (the form was just hidden instead of closed) and kept a dictionary of active forms to prevent the same form from being activated more than once. This looks like a modal form, supports multiple pop-up forms at once, but does not tie up the main GUI thread.

ADDENDUM:我的解决方案是一个基本表单,它提供了OK和CANCEL按钮来发出Completed和Cancelled事件; OK称为子类覆盖的虚拟ValidateData。调用表单使用属性来避免每次重新创建表单(表单只是隐藏而不是关闭)并保留活动表单的字典以防止同一表单被激活多次。这看起来像一个模态形式,一次支持多个弹出窗体,但不会占用主GUI线程。

7 个解决方案

#1


4  

I agree with rslite and Mitchel Sellers. Creating a non-Modal form to display the information needed is the best route to go. If you have multiple messages, you might want to consider putting them into a ListBox and have the user double-click on them to get the full information needing to be displayed.

我同意rslite和Mitchel Sellers的观点。创建非模态表单以显示所需信息是最佳途径。如果您有多条消息,可能需要考虑将它们放入ListBox并让用户双击它们以获取需要显示的完整信息。

#2


4  

I suggest going with a non-modal approach, like others said, but a little more specific:

我建议采用非模态方法,就像其他人说的那样,但更具体一点:

  • If you just want a notification, you may try a balloon tip (TNA or your own), or a window that is like the Outlook mail notification or the notification many instant messengers like Trillian display.
  • 如果您只是想要通知,您可以尝试使用气球提示(TNA或您自己的),或者像Outlook邮件通知或许多即时信使(如Trillian)显示的通知。

  • If you just want to give the user a chance to act, use a non-modal form but remember that he might very well just click it away.
  • 如果您只是想让用户有机会采取行动,请使用非模态表单,但请记住,他可能只需将其单击即可。

  • If the user MUST act upon your message, you should go modal. Note that the owner window will still be painted and you can refresh your GUI - a modal dialog, after all, has a message pump, otherwise it would not work. I did something like that recently, we had a background worker thread pool that would carry on any actions and fire events for the GUI to refresh, and a modal wait dialog that still got its messages pump. The owner window did update with the background action as expected.
  • 如果用户必须对你的消息采取行动,你应该采取模态。请注意,所有者窗口仍然会被绘制,您可以刷新GUI - 毕竟,模式对话框有一个消息泵,否则它将无法工作。我最近做了类似的事情,我们有一个后台工作线程池,可以进行任何操作和激活事件以供GUI刷新,还有一个模态等待对话框仍然可以获取其消息。所有者窗口确实按预期更新了后台操作。

#3


2  

What about adding a NotifyIcon to your application and displaying a balloon tip. The down side is that the notification will disappear after a short time, but maybe that's best for your users if they don't need to take action.

如何将NotifyIcon添加到您的应用程序并显示气球提示。缺点是通知会在短时间后消失,但如果用户不需要采取措施,这可能对您的用户最有利。

#4


1  

I would solve this by using a non-modal dialog box or maybe some tooltips depending on the specific requirements.

我会通过使用非模态对话框或某些工具提示来解决这个问题,具体取决于具体要求。

#5


1  

If you don't want it blocking, I'd just create your own simple form to do the display. That is how I have completed items for clients before when a non-blocking solution was needed. But keep in mind that if you do it as non-blocking that users could get multiples up and be overwhelmed if they are really "you must act" type items.

如果您不想阻止它,我只需创建您自己的简单表单来进行显示。这就是我在需要非阻塞解决方案之前为客户完成项目的方法。但请记住,如果你这样做是非阻塞的,那么如果用户真的是“你必须行动”的类型项,那么用户可能会倍增并被淹没。

#6


1  

thanks to everyone who contributed suggestions, it seems that my solution was about right ;-)

感谢所有提出建议的人,似乎我的解决方案是正确的;-)

my solution was a base form that provided OK and CANCEL buttons to emit Completed and Cancelled events; OK called a virtual ValidateData for subclass override. The calling form used properties to avoid recreating the form each time (the form was just hidden instead of closed) and kept a dictionary of active forms to prevent the same form from being activated more than once. This looks like a modal form, supports multiple pop-up forms at once, but does not tie up the main GUI thread.

我的解决方案是一个基本表单,它提供了OK和CANCEL按钮来发出Completed和Cancelled事件; OK称为子类覆盖的虚拟ValidateData。调用表单使用属性来避免每次重新创建表单(表单只是隐藏而不是关闭)并保留活动表单的字典以防止同一表单被激活多次。这看起来像一个模态形式,一次支持多个弹出窗体,但不会占用主GUI线程。

#7


-1  

If you want the MessageBox look and feel just show it in a background thread.

如果您希望MessageBox外观只是在后台线程中显示它。

ThreadPool.QueueUserWorkItem( (state) =>
    {
         MessageBox.Show("Your message");
    });

(code not tested)

(代码未经测试)

#1


4  

I agree with rslite and Mitchel Sellers. Creating a non-Modal form to display the information needed is the best route to go. If you have multiple messages, you might want to consider putting them into a ListBox and have the user double-click on them to get the full information needing to be displayed.

我同意rslite和Mitchel Sellers的观点。创建非模态表单以显示所需信息是最佳途径。如果您有多条消息,可能需要考虑将它们放入ListBox并让用户双击它们以获取需要显示的完整信息。

#2


4  

I suggest going with a non-modal approach, like others said, but a little more specific:

我建议采用非模态方法,就像其他人说的那样,但更具体一点:

  • If you just want a notification, you may try a balloon tip (TNA or your own), or a window that is like the Outlook mail notification or the notification many instant messengers like Trillian display.
  • 如果您只是想要通知,您可以尝试使用气球提示(TNA或您自己的),或者像Outlook邮件通知或许多即时信使(如Trillian)显示的通知。

  • If you just want to give the user a chance to act, use a non-modal form but remember that he might very well just click it away.
  • 如果您只是想让用户有机会采取行动,请使用非模态表单,但请记住,他可能只需将其单击即可。

  • If the user MUST act upon your message, you should go modal. Note that the owner window will still be painted and you can refresh your GUI - a modal dialog, after all, has a message pump, otherwise it would not work. I did something like that recently, we had a background worker thread pool that would carry on any actions and fire events for the GUI to refresh, and a modal wait dialog that still got its messages pump. The owner window did update with the background action as expected.
  • 如果用户必须对你的消息采取行动,你应该采取模态。请注意,所有者窗口仍然会被绘制,您可以刷新GUI - 毕竟,模式对话框有一个消息泵,否则它将无法工作。我最近做了类似的事情,我们有一个后台工作线程池,可以进行任何操作和激活事件以供GUI刷新,还有一个模态等待对话框仍然可以获取其消息。所有者窗口确实按预期更新了后台操作。

#3


2  

What about adding a NotifyIcon to your application and displaying a balloon tip. The down side is that the notification will disappear after a short time, but maybe that's best for your users if they don't need to take action.

如何将NotifyIcon添加到您的应用程序并显示气球提示。缺点是通知会在短时间后消失,但如果用户不需要采取措施,这可能对您的用户最有利。

#4


1  

I would solve this by using a non-modal dialog box or maybe some tooltips depending on the specific requirements.

我会通过使用非模态对话框或某些工具提示来解决这个问题,具体取决于具体要求。

#5


1  

If you don't want it blocking, I'd just create your own simple form to do the display. That is how I have completed items for clients before when a non-blocking solution was needed. But keep in mind that if you do it as non-blocking that users could get multiples up and be overwhelmed if they are really "you must act" type items.

如果您不想阻止它,我只需创建您自己的简单表单来进行显示。这就是我在需要非阻塞解决方案之前为客户完成项目的方法。但请记住,如果你这样做是非阻塞的,那么如果用户真的是“你必须行动”的类型项,那么用户可能会倍增并被淹没。

#6


1  

thanks to everyone who contributed suggestions, it seems that my solution was about right ;-)

感谢所有提出建议的人,似乎我的解决方案是正确的;-)

my solution was a base form that provided OK and CANCEL buttons to emit Completed and Cancelled events; OK called a virtual ValidateData for subclass override. The calling form used properties to avoid recreating the form each time (the form was just hidden instead of closed) and kept a dictionary of active forms to prevent the same form from being activated more than once. This looks like a modal form, supports multiple pop-up forms at once, but does not tie up the main GUI thread.

我的解决方案是一个基本表单,它提供了OK和CANCEL按钮来发出Completed和Cancelled事件; OK称为子类覆盖的虚拟ValidateData。调用表单使用属性来避免每次重新创建表单(表单只是隐藏而不是关闭)并保留活动表单的字典以防止同一表单被激活多次。这看起来像一个模态形式,一次支持多个弹出窗体,但不会占用主GUI线程。

#7


-1  

If you want the MessageBox look and feel just show it in a background thread.

如果您希望MessageBox外观只是在后台线程中显示它。

ThreadPool.QueueUserWorkItem( (state) =>
    {
         MessageBox.Show("Your message");
    });

(code not tested)

(代码未经测试)