如何保存此调用线程?

时间:2019-04-12 12:13:29

标签: c# multithreading

我正在使用在此页面上找到的自定义消息框,包括来源: https://www.c-sharpcorner.com/blogs/creating-customized-message-box-with-animation-effect-in-windows-form

在大多数情况下,它可以正常工作,但有时当我同时弹出两个消息框时,则该函数崩溃:

 class MsgBox : Form
 {

    private static MsgBox _msgBox;

    public static MsgDlgResult Show(string message, string title, Buttons buttons, IconImage icon)
    {
        _msgBox = new MsgBox();
        _msgBox._lblMessage.Text = message;
        _msgBox._lblTitle.Text = title;

        MsgBox.InitButtons(buttons);
        MsgBox.InitIcon(icon);

        _msgBox.Size = MsgBox.MessageSize(message);
        _msgBox.ShowDialog();
        MessageBeep(0);
        return _buttonResult;
    }

    private static void ButtonClick(object sender, EventArgs e)
    {
        Button btn = (Button)sender;

        switch (btn.Name)
        {
            case "Abort":
                _buttonResult = MsgDlgResult.Abort;
                break;

            case "Retry":
                _buttonResult = MsgDlgResult.Retry;
                break;

            ......

        }


       ----->>>> _msgBox.Dispose();
     }
 }

我收到错误消息 System.InvalidOperationException:“跨线程操作无效:从创建该线程的线程之外的其他线程访问控件”

如何使此类线程安全或至少在c#中使此调用安全?但是我仍然必须能够一次拥有多个消息框。

更新 我的电话:

 MessageBoxResult result = MsgBox.Show("My Message test", string.Empty, MsgBox.Buttons.OK, MsgBox.IconImage.Error);

2 个答案:

答案 0 :(得分:0)

让我猜...

  • 您创建第一个对话框,并将其分配给_msgBox变量。
  • 然后创建第二个对话框,然后再次将其分配给相同的_msgBox变量(因为它是static)。
  • 您在第一个对话框中单击按钮
  • 事件句柄触发并尝试处理第二个对话框
  • 您得到了例外

此解决方案中的私有变量不应设为静态。如果它们是静态的-此类的所有实例都引用变量的相同实例,这里指向相同的_msgBox_buttonResult

确保在调用静态Show时被调用的类具有私有构造函数。在此构造函数中,您应该分配各自的值。
或在声明变量时分配值。

答案 1 :(得分:-1)

下面的解决方案非常臭,但是您在这里:

步骤1:将现有方法Show重命名为ShowUnsafe

public static MsgDlgResult ShowUnsafe(string message, string title, Buttons buttons, IconImage icon)

步骤2:在类MainForm内添加静态属性MsgBox

public static Form MainForm { get; set; }

步骤3:在应用程序主窗体的构造函数中添加以下行:

MsgBox.MainForm = this;

步骤4::在类Show内添加一个新方法MsgBox

public static MsgDlgResult Show(string message, string title, Buttons buttons, IconImage icon)
{
    if (!MainForm.IsHandleCreated) return default(MsgDlgResult);
    if (MainForm.InvokeRequired)
    {
        MsgDlgResult result = default(MsgDlgResult);
        Thread.MemoryBarrier();
        MainForm.Invoke((MethodInvoker)delegate { result = ShowSafe(message, title, buttons, icon); });
        Thread.MemoryBarrier();
        return result;
    }
    else
    {
        return ShowSafe(message, title, buttons, icon);
    }
}