1

我已经获得了多线程应用程序,并且已经完成。static此应用程序中的所有消息框都由实用程序类中的单个方法正确调用。这种方法是:

public static void ErrMsg(String strMsg, Exception ex = null)
{
    ...
    if (ex == null)
        MessageBox.Show(strMsg, "MyApp", MessageBoxButtons.OK, MessageBoxIcon.Warning);
    ...
}

显然,这不提供IWin32Window所有者,当我使用此方法从后台线程池线程调用错误消息时,这给我带来了问题。问题是在我的主窗体后面显示的一个已知消息框。看:

  1. 在 WPF 中使用 Backgroundworker 为主应用程序弹出一个 MessageBox

等。我可以将SynchronisationContext当​​前线程的传递给ErrMsg并执行

synchronizationContext.Send(callback => 
    MessageBox.Show("Some error message for the user"), null);

但是有 700+ 次调用此方法,其中大部分在 UI 线程上,不会导致问题。我的问题是:我怎样才能修改该ErrMsg方法,以便我的消息框出现在前面,SynchronisationContex而无需修改所有 700 多次对该方法的调用?

谢谢你的时间。


编辑。@Dmitry 的想法很棒。但是,如果活动窗体没有焦点或者是 MdiChild 窗体,Form.ActiveForm则将返回 null。为了解决这个问题,我使用Application.OpenForms.Cast<Form>().Last()获取最后一个活动表单,无论是 MdiChild 还是其他。代码现在...

Form activeForm = Application.OpenForms.Cast<Form>().Last();
if (ex == null)
{
    activeForm.Invoke(new ShowErrMsg(text => 
        MessageBox.Show(activeForm, 
            text, 
            "UserCost",
            MessageBoxButtons.OK, 
            MessageBoxIcon.Warning)), 
        strMsg);
}
4

1 回答 1

1

尝试使用Form.ActiveForm静态属性作为 MessageBox.Show(...) 的第一个参数。还应该使用线程安全调用。
例子:

private delegate void ShowErrMsgMethod(string text);

public static void ErrMsg(String strMsg, Exception ex = null)
{
    ...
    if (ex == null)
    {
        Form activeForm = Form.ActiveForm ?? Application.OpenForms.Cast<Form>().Last();
        activeForm.Invoke(new ShowErrMsgMethod(text => MessageBox.Show(activeForm, text, "MyApp", MessageBoxButtons.OK, MessageBoxIcon.Warning)), strMsg);
    }
    ...
}

编辑:针对打开其他表单的情况进行了改进。删除了对主要形式的引用。
EDIT2:针对Form.ActiveForm == null.

于 2013-11-14T16:19:25.667 回答