对话框如何在不阻塞主线程的情况下阻止代码执行?

时间:2016-09-20 21:15:15

标签: c# dialog

在C#WinForms中,如果打开一个对话框,它会在显示对话框后继续执行代码,直到您单击“确定”。这显然是正在发生的事情。但是,在对话框打开时,主线程仍然可以执行代码。因此对话框不会阻塞主线程,但它阻止了代码的特定范围。

我很好奇这是如何运作的。可能/你将如何实现这样的事情? (我不想这样做,我只是意识到我并不完全理解对话框如何在不阻塞线程执行的情况下工作。)

考虑这个带有两个按钮和标签的示例代码和项目。标签显示计数器的值。计时器每500毫秒递增一次计数器。其中一个按钮打开一个对话框。另一个运行一个循环,调用Thread.Sleep一秒钟十次。当对话框打开时,您会注意到标签计数器递增,而thread.sleep会阻止所有计时器执行,直到它完成。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace MainThreadPauser
{
    public partial class Form1 : Form
    {
        int counter = 0;
        public Form1()
        {
            InitializeComponent();
            System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
            t.Interval = 500;
            t.Enabled = true;
            t.Tick += new EventHandler(t_Tick);
            t.Start();
        }

        void t_Tick(object sender, EventArgs e)
        {
            BeginInvoke((Action)(() => {
                AddToCounter();
            }));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MyDialog dlg = new MyDialog();
            dlg.ShowDialog(this);

            AddToCounter(5000);
        }

        private void AddToCounter(int value = 1)
        {
            counter += value;
            label1.Text = counter.ToString();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            for (int x = 0; x < 10; x++)
            {
                Thread.Sleep(1000);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:2)

简而言之:

你的gui线程运行一个messagepump,它处理点击/移动/键等消息。

当您打开模式对话框时,消息对话框将运行一个新的&#39;对话框(while循环)中的messagepump / loop,因此会处理所有窗口消息,但它会阻止调用show对话框的当前方法,直到关闭对话框为止。这就是为什么计时器(他们处理windowmessages)并重新绘制窗口仍然有效。该对话框将禁用您的窗口,因此您无法通过该对话框。