【问题标题】:Close MessageBox when incoming new message收到新消息时关闭 MessageBox
【发布时间】:2016-02-18 01:57:57
【问题描述】:

我创建了简单的应用程序来使用 C# 和 GsmComm 库发送和接收消息。如果有新的传入消息,我的应用程序将显示新消息到达的 messageBox。我的问题是当我有很多新消息时,messageBox 会显示很多 messageBox 通知。如何使用代码只显示最后一个消息框?

这个我的代码:

private void comm_MessageReceived(object sender, MessageReceivedEventArgs e)
{
    var obj = e.IndicationObject;
    if (obj is MemoryLocation)
    {
        var loc = (MemoryLocation)obj;
        var msg = string.Format("New message received in storage \"{0}\", index {1}.",
                                loc.Storage, loc.Index);
        MessageBox.Show(msg);
        return;
    }
}

我很困惑解决这个问题,我尝试了另一种方式使用表单来显示新传入的通知form1.showDialog();,但是当打开新表单时,第一个表单显示无法关闭。这是我的参考:https://stackoverflow.com/a/13445167/3319555

如果有人可以帮助我,我真的很感谢......谢谢

【问题讨论】:

    标签: c# forms winforms messagebox


    【解决方案1】:

    如果您使用第二个解决方案来显示带有form.ShowDialog() 的表单,您可以将表单存储在列表中。然后,当需要显示新表单时,您可以遍历列表并使用form.Close() 关闭每个打开的表单。假设您的 comm_MessageReceieved 方法在另一个线程上运行,我假设它是通过 IO 完成端口驱动的,那么可能是这样的?

    List<MyForm> formList = new List<MyForm>();
    
    readonly object formListLock = new object();
    
    private void comm_MessageReceived(object sender, MessageReceivedEventArgs e)
    {
        /// you need to lock the List for thread safe access
        lock (formListLock) 
        {
            /// iterate over a copy of the list to avoid mutating the list under iteration
            foreach (MyForm form in formList.ToList())
            {
                form.ThreadSafeClose();
            }
        }
    
        string msg = "message";
        using (MyForm form = new MyForm(msg))
        {
            lock (formListLock) { formList.Add(form); }
            form.ShowDialog();
            lock (formListLock) { formList.Remove(form); }
        }
    }
    

    这只是我的想法,但可能是您可以采取的另一个可能的方向。

    您必须对 form.Close() 进行线程安全调用,以便它在表单的 UI 线程上运行。阅读有关调用here 的信息。关于这个主题有很多关于 SO 的信息。这可以像在表单类中添加类似以下方法一样简单:

    public void ThreadSafeClose()
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new Action(Close));  /// or BeginInvoke...
        }
        else
        {
            Close();
        }
    }
    

    在此处阅读有关列表的更多信息:https://msdn.microsoft.com/en-us/library/6sh2ey19%28v=vs.110%29.aspx

    在此处阅读有关锁定语句的更多信息:https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

    在此处阅读有关线程同步的更多信息:https://msdn.microsoft.com/en-us/library/ms173179.aspx

    还有许多线程安全的集合可能满足您的需求,例如ConcurrentBag.

    【讨论】:

    • 我试过了,但是当我运行我的项目时,我清楚地收到了第一条消息,但是当第二条消息传入时,我收到了这样的消息 cross thread operation not valid: 'MyForm' accessed from a thread other than the thread it was created on 有什么建议吗?
    • 您必须对 form.Close 进行线程安全调用,以便它在表单的 UI 线程上运行。
    • 我必须在哪里打电话给ThreadSafeClose()?以我显示为对话消息或其他形式的形式?请告诉我,谢谢
    • 我已经在上面的示例中向您展示过。当您需要从另一个线程关闭表单时,应该调用form.ThreadSafeClose()。这就是从不是表单的 UI 线程的线程中关闭表单(或访问的任何方法调用或表单属性)的方式。
    • 对不起,我没有检查你上面的建议代码,.. 它真的很棒,它工作,.. 非常感谢
    猜你喜欢
    • 2016-03-28
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-24
    • 1970-01-01
    • 2019-05-23
    相关资源
    最近更新 更多