简体   繁体   中英

How do dialogs prevent code execution without blocking the main thread?

In C# WinForms, if you open a dialog box, it does not continue executing code after the show dialog until you click ok. This much is obviously what is happening. However, the main thread can still execute code while the dialog is open. So the dialog box is not blocking the main thread, but it is blocking the specific scope of follow on code.

I'm curious how exactly this works. Could / how would you implement something like this? (I don't want to do this, I just realized that I don't understand entirely how the dialog boxes work without blocking thread execution.)

Consider this sample code and project with two buttons and a label. The label displays the value of a counter. A timer increments the counter every 500 milliseconds. One of the buttons opens a dialog. The other runs a loop that calls Thread.Sleep for one second ten times. You'll notice the label counter increments while the dialog is open, while the thread.sleep blocks all timer execution until it finishes.

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);
            }
        }
    }
}

In short:

Your gui thread runs a messagepump, it handles click/move/keys etc messages.

When you open a modal dialog, the message dialog will run a 'new' messagepump/loop inside the dialog (while loop) , so all window messages are handled, but it will block the current method where the show dialog is called until you close the dialog. Thats why timers (they work on windowmessages) and repainting the window is still working. The dialog will disable your window, so you can't pass the dialog.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM