Application.Run()在没有调试器的Release版本中的运行方式与在w /或Debug版本中的运行方式不同

时间:2010-11-08 07:22:17

标签: c# multithreading

我在使用C#中的处理线程时遇到问题。基本上,线程在新消息到达或发送时管理聊天窗口,不幸的是,我根据运行环境发生了不同的情况。

运行Debug构建(带或不带调试器)或调试器下的Release构建时,Process()函数正常运行,显示窗口并接收消息。

但是,在没有调试器的情况下运行Release版本时,Application.Run()调用似乎停止了主Process()线程的处理(请注意,此调用发生在处理线程的子线程下)并且所以不再进行处理。

通过使用MessageBox.Show()调用,我确定Application.Run()是在不再显示消息框之前进行的最后一次调用(并且它们应该显示为接收了多少消息每次while循环运行时。)

有没有人知道为什么Application.Run()调用在这种情况下表现不同?

    /// <summary>
    /// Processes the IM message queue, managing the chat windows and messages.
    /// </summary>
    private void Process()
    {
        try
        {
            MessageBox.Show("MessageQueue process has started!");

            while (this.m_Running)
            {
                List<Message> messages = null;
                lock (this.m_Lock)
                {
                    messages = new List<Message>(this.m_Messages);
                    MessageBox.Show("MessageQueue received " + this.m_Messages.Count + " messages on this spin.");
                    this.m_Messages.Clear();
                }

                // Process all the messages
                foreach (Message m in messages)
                {
                    Contact c = m.Contact;

                    if (!this.m_Windows.Keys.Contains(c.ID) || this.m_Windows[c.ID] == null)
                    {
                        MessageBox.Show("MessageQueue is creating a new window.");
                        bool complete = false;
                        Thread t = new Thread(() =>
                            {
                                try
                                {
                                    ChatWindow w = new ChatWindow(this, c, new Contact(this.m_Client.JID, null));
                                    w.Load += (sender, e) =>
                                        {
                                            if (m.IsTo)
                                                w.AppendSentMessage(m.To, m.Data);
                                            else if (m.IsFrom)
                                                w.AppendRecievedMessage(m.From, m.Data);

                                            w.UpdateStatus(c);
                                        };
                                    w.FormClosed += (sender, e) =>
                                        {
                                            this.m_Windows[c.ID] = null;
                                        };
                                    c.StatusUpdated += (sender, e) =>
                                        {
                                            RoketPack.Manager.VoidLambda lambda = () =>
                                            {
                                                w.UpdateStatus(c);
                                            };

                                            if (w.InvokeRequired)
                                                w.Invoke(lambda);
                                            else
                                                lambda();
                                        };
                                    MessageBox.Show("MessageQueue is now showing the new window.");
                                    w.Show();
                                    if (!this.m_Windows.Keys.Contains(c.ID))
                                        this.m_Windows.Add(c.ID, w);
                                    else
                                        this.m_Windows[c.ID] = w;
                                    complete = true;
                                    MessageBox.Show("MessageQueue is now running the new window.");
                                    Application.Run(w);
                                    MessageBox.Show("MessageQueue is now closing the window.");
                                }
                                catch (Exception ex)
                                {
                                    MessageBox.Show(ex.ToString());
                                    complete = true;
                                }
                            });
                        t.Name = "IM Chat Window - " + c.ID;
                        t.IsBackground = true;
                        t.Start();

                        // We have to wait until the form has been added to the dictionary.
                        while (!complete) ;
                    }
                    else
                    {
                        RoketPack.Manager.VoidLambda lambda = () =>
                            {
                                if (m.IsTo)
                                    this.m_Windows[c.ID].AppendSentMessage(m.To, m.Data);
                                else if (m.IsFrom)
                                    this.m_Windows[c.ID].AppendRecievedMessage(m.From, m.Data);
                                MessageBox.Show("MessageQueue appended the message to the chat window.");
                            };

                        MessageBox.Show("MessageQueue received a message and is now forwarding it onto the chat window.");
                        if (this.m_Windows[c.ID].InvokeRequired)
                            this.m_Windows[c.ID].Invoke(lambda);
                        else
                            lambda();
                    }
                }

                // Sleep for 10 milliseconds.
                Thread.Sleep(10);
            }
        }
        finally
        {
            MessageBox.Show("MessageQueue process has terminated!");
        }
    }

2 个答案:

答案 0 :(得分:1)

您是否意识到Application.Run在应用程序关闭之前不会返回?

您似乎也在从子线程调用Application.Run

答案 1 :(得分:1)

除了leppie所写的内容,这看起来是一个糟糕的起点:

while (!complete);

我不确切知道提升变量和可见性的确切含义,但紧密循环几乎总是一个坏主意。

通常最好使用Wait / Notify方法或Auto/ManualResetEvent