c# 线程的基础教学(winform 电梯模拟)

目录

[案例一: 启动与停止](#案例一: 启动与停止)

[案例二: 加热装置](#案例二: 加热装置)

案例三:电梯


在图形用户界面中,主线程负责界面更新,如果只在主线程中运行任务,容易造成UI卡顿。

案例一: 启动与停止

创建winform 项目

在界面中添加2个button

并设计点击事件,start按钮点击后会切换颜色。

我们定义一个action1(),一个简单的循环。

代码如下:

cs 复制代码
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Threading; 

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        private static bool istart = false;//start 按钮是否按下
        private static bool istop = false;//stop 按钮是否按下

        public Form1()
        {
            InitializeComponent();
        }

        private void button_start_Click(object sender, EventArgs e)
        {
            istart = !istart;
            if (istart){
                button_start.BackColor = Color.Green;
                MessageBox.Show("已启动");
                action1();
            }
            else {
                button_start.BackColor = Color.White;}



        }

        private void button_stop_Click(object sender, EventArgs e)
        {
            istop = !istop;
        }


        private void action1()
        {
            while (istart)
            {
                if (istop)
                {
                    break;
                }              
            }
        }




    }

}

运行,action1被成功调用了,但我们没法关闭它,UI界面卡住了。

原因很简单。

WinForms的UI操作必须在主线程(UI线程)执行,而while(istart)循环在UI线程中无限运行,导致:

  • 界面无法刷新(按钮状态不更新)
  • 无法处理其他用户输入(如点击STOP按钮)

我们使用,线程的方式运行action1:

Thread th_action1 = new Thread(action1);

th_action1.Start();

cs 复制代码
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Threading; 

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        private static bool istart = false;//start 按钮是否按下
        private static bool istop = false;//stop 按钮是否按下

        public Form1()
        {
            InitializeComponent();
        }

        private void button_start_Click(object sender, EventArgs e)
        {
            istart = !istart;
            if (istart){
                button_start.BackColor = Color.Green;
                Thread th_action1 = new Thread(action1);
                th_action1.Start();
            }
            else {
                button_start.BackColor = Color.White;}



        }

        private void button_stop_Click(object sender, EventArgs e)
        {
            istop = !istop;
        }


        private void action1()
        {
            while (istart)
            {
                if (istop)
                {
                    button_start.BackColor = Color.White;
                    break;
                }              
            }
        }




    }

}

运行后,可以正常使用start 和 stop 按钮。

案例二: 加热装置

在案例1的基础上,添加textbox1

在action1 中,不断增加水温

cs 复制代码
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Threading; 

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        private static bool istart = false;//start 按钮是否按下
        private static bool istop = false;//stop 按钮是否按下
        private static int temperature =  0;

        public Form1()
        {
            InitializeComponent();
        }

        private void button_start_Click(object sender, EventArgs e)
        {
            istart = !istart;
            if (istart){
                button_start.BackColor = Color.Green;
                Thread th_action1 = new Thread(action1);
                th_action1.Start();
            }
            else {
                button_start.BackColor = Color.White;}


        }

        private void button_stop_Click(object sender, EventArgs e)
        {
            istop = !istop;
        }


        private void action1()
        {
            


            while (istart)
            {

                temperature = temperature + 1;
                textBox1.Text = temperature.ToString();
                Thread.Sleep(500);


                if (istop)
                {
                    button_start.BackColor = Color.White;
                    break;
                }              
            }
        }




    }

}

运行,

成功报错。

action1 已经进入新线程th_action1,,而操作ui我们得回主线程。

所以,做如下修改:

private void action1()

{

while (istart)

{

temperature = temperature + 1;

//textBox1.Text = temperature.ToString();//报错

//this.BeginInvoke(new Action(() => { textBox1.Text = temperature.ToString(); }));//法一

this.Invoke((MethodInvoker)delegate {textBox1.Text = temperature.ToString();});//法二

Thread.Sleep(1500);

if (istop)

{

break;

}

}

}

其中,Invoke是同步的,BeginInvoke是异步的。

也就是说,使用Invoke时,如果UI线程正忙,调用action1会被阻塞。使用BeginInvoke时,会继续执行后续代码,而委托会在UI线程的消息循环中排队等待执行。

cs 复制代码
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Threading; 

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        private static bool istart = false;//start 按钮是否按下
        private static bool istop = false;//stop 按钮是否按下
        private static int temperature =  0;

        public Form1()
        {
            InitializeComponent();
        }

        private void button_start_Click(object sender, EventArgs e)
        {
            istart = !istart;
            
            if (istart){
                button_start.BackColor = Color.Green;
                Thread th_action1 = new Thread(action1);
                th_action1.Start();
                
            }
            else {
                button_start.BackColor = Color.White;}


        }

        private void button_stop_Click(object sender, EventArgs e)
        {
            istop = !istop;
        }


        private void action1()//加热
        {
            
            while (istart)
            {

                temperature = temperature + 1;
                //textBox1.Text = temperature.ToString();//报错
                //this.BeginInvoke(new Action(() => { textBox1.Text = temperature.ToString(); }));//法一
                this.Invoke((MethodInvoker)delegate {textBox1.Text = temperature.ToString();});//法二

                Thread.Sleep(1000);

                if (istop)
                {
                    button_start.BackColor = Color.White;
                    istop = false;
                    break;
                }              
            }
        }




    }

}

现在,我们加入室温的降温(每三秒降低1度)。

private void action2()//降温

{

while (true) {

if (temperature > 0) {

temperature = temperature - 1;

this.BeginInvoke(new Action(() => { textBox1.Text = temperature.ToString(); }));

Thread.Sleep(3000);

}

}

}

在加载form1时 就开始运行。

cs 复制代码
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Threading; 

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        private static bool istart = false;//start 按钮是否按下
        private static bool istop = false;//stop 按钮是否按下
        private static int temperature =  0;

        public Form1()
        {
            InitializeComponent();
            Thread th_action2 = new Thread(action2);
            th_action2.Start();
        }

        private void button_start_Click(object sender, EventArgs e)
        {
            istart = !istart;
            
            if (istart){
                button_start.BackColor = Color.Green;
                Thread th_action1 = new Thread(action1);
                th_action1.Start();
                
            }
            else {
                button_start.BackColor = Color.White;}


        }

        private void button_stop_Click(object sender, EventArgs e)
        {
            istop = !istop;
        }


        private void action1()//加热
        {
            
            while (istart)
            {

                temperature = temperature + 1;
                //textBox1.Text = temperature.ToString();//报错
                //this.BeginInvoke(new Action(() => { textBox1.Text = temperature.ToString(); }));//法一
                this.Invoke((MethodInvoker)delegate {textBox1.Text = temperature.ToString();});//法二

                Thread.Sleep(1000);

                if (istop)
                {
                    button_start.BackColor = Color.White;
                    istop = false;
                    break;
                }              
            }
        }

        private void action2()//降温
        {
            while (true) {
                if (temperature > 0) {
                    temperature = temperature - 1;
                    this.BeginInvoke(new Action(() => { textBox1.Text = temperature.ToString(); }));
                    Thread.Sleep(3000);
                }

            }
            
        }














    }

}

随着action越来越多,逻辑越来越复杂,这种写法并不规范。

对此,做出修改

1.使用lock同步机制保护共享变量_temperature,降低多线程抢变量风险。

2.采用async/await模式

完整代码如下:

cs 复制代码
using System;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        private bool _istart;
        private int _temperature;
        private readonly object _tempLock = new object();
        private CancellationTokenSource _cts;

        public Form1()
        {
            InitializeComponent();
            Load += Form1_Load;
        }

        private async void Form1_Load(object sender, EventArgs e)
        {
            await Task.Run(() => action2()); // 启动降温任务
        }

        private void button_start_Click(object sender, EventArgs e)
        {
            _istart = !_istart;
            if (_istart)
            {
                _cts = new CancellationTokenSource();
                button_start.BackColor = Color.Green;
                _ = action1(_cts.Token); // 启动加热任务
            }
            else
            {
                _cts?.Cancel();
                button_start.BackColor = Color.White;
            }
        }





        private async Task action1(CancellationToken token)
        {
            while (!token.IsCancellationRequested)
            {
                lock (_tempLock)
                {
                    _temperature++;
                }
                UpdateTemperatureText();
                try
                {
                    await Task.Delay(1000, token);
                }
                catch (TaskCanceledException)
                {
                    break;
                }
            }
        }

        private async Task action2()
        {
            while (true)
            {
                lock (_tempLock)
                {
                    if (_temperature > 0) _temperature--;
                }
                UpdateTemperatureText();
                await Task.Delay(3000);
            }
        }

        private void UpdateTemperatureText()
        {
            if (textBox1.InvokeRequired)
            {
                textBox1.Invoke((Action)UpdateTemperatureText);
                return;
            }
            textBox1.Text = _temperature.ToString();
        }
    }
}
cs 复制代码
namespace WindowsFormsApp4
{
    partial class Form1
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.button_start = new System.Windows.Forms.Button();
            this.button_stop = new System.Windows.Forms.Button();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // button_start
            // 
            this.button_start.Location = new System.Drawing.Point(209, 661);
            this.button_start.Name = "button_start";
            this.button_start.Size = new System.Drawing.Size(248, 128);
            this.button_start.TabIndex = 0;
            this.button_start.Text = "start";
            this.button_start.UseVisualStyleBackColor = true;
            this.button_start.Click += new System.EventHandler(this.button_start_Click);
            // 
            // button_stop
            // 
            this.button_stop.Location = new System.Drawing.Point(637, 661);
            this.button_stop.Name = "button_stop";
            this.button_stop.Size = new System.Drawing.Size(248, 128);
            this.button_stop.TabIndex = 1;
            this.button_stop.Text = "stop";
            this.button_stop.UseVisualStyleBackColor = true;
            //this.button_stop.Click += new System.EventHandler(this.button_stop_Click);
            // 
            // textBox1
            // 
            this.textBox1.Font = new System.Drawing.Font("宋体", 35F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.textBox1.Location = new System.Drawing.Point(526, 245);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(121, 87);
            this.textBox1.TabIndex = 2;
            this.textBox1.Text = "0";
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Font = new System.Drawing.Font("宋体", 35F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.label1.Location = new System.Drawing.Point(292, 248);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(240, 70);
            this.label1.TabIndex = 3;
            this.label1.Text = "水温:";
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(1189, 881);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.button_stop);
            this.Controls.Add(this.button_start);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Button button_start;
        private System.Windows.Forms.Button button_stop;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Label label1;
    }
}

案例三:电梯

创建c# winform 项目 lift

添加几个button 和 textbox

cs 复制代码
namespace lift
{
    partial class Form1
    {
        /// <summary>
        ///  Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        ///  Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        ///  Required method for Designer support - do not modify
        ///  the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            textBox_layer = new TextBox();
            label1 = new Label();
            textBox_door = new TextBox();
            label2 = new Label();
            button_L1 = new Button();
            button_L2 = new Button();
            button_L3 = new Button();
            button_L4 = new Button();
            label3 = new Label();
            SuspendLayout();
            // 
            // textBox_layer
            // 
            textBox_layer.Font = new Font("Microsoft YaHei UI", 40F);
            textBox_layer.Location = new Point(228, 53);
            textBox_layer.Name = "textBox_layer";
            textBox_layer.Size = new Size(124, 109);
            textBox_layer.TabIndex = 0;
            textBox_layer.Text = "1";
            // 
            // label1
            // 
            label1.AutoSize = true;
            label1.Font = new Font("Microsoft YaHei UI", 18F);
            label1.Location = new Point(12, 85);
            label1.Name = "label1";
            label1.Size = new Size(200, 46);
            label1.TabIndex = 1;
            label1.Text = "目前楼层:";
            // 
            // textBox_door
            // 
            textBox_door.Font = new Font("Microsoft YaHei UI", 20F);
            textBox_door.Location = new Point(196, 211);
            textBox_door.Name = "textBox_door";
            textBox_door.Size = new Size(170, 58);
            textBox_door.TabIndex = 3;
            textBox_door.Text = "CLOSE";
            // 
            // label2
            // 
            label2.AutoSize = true;
            label2.Font = new Font("Microsoft YaHei UI", 18F);
            label2.Location = new Point(112, 421);
            label2.Name = "label2";
            label2.Size = new Size(200, 46);
            label2.TabIndex = 4;
            label2.Text = "电梯按钮:";
            // 
            // button_L1
            // 
            button_L1.Location = new Point(85, 723);
            button_L1.Name = "button_L1";
            button_L1.Size = new Size(82, 72);
            button_L1.TabIndex = 5;
            button_L1.Text = "1";
            button_L1.UseVisualStyleBackColor = true;
            button_L1.Click += button_L1_Click;
            // 
            // button_L2
            // 
            button_L2.Location = new Point(295, 723);
            button_L2.Name = "button_L2";
            button_L2.Size = new Size(82, 72);
            button_L2.TabIndex = 6;
            button_L2.Text = "2";
            button_L2.UseVisualStyleBackColor = true;
            button_L2.Click += button_L2_Click;
            // 
            // button_L3
            // 
            button_L3.Location = new Point(85, 543);
            button_L3.Name = "button_L3";
            button_L3.Size = new Size(82, 72);
            button_L3.TabIndex = 7;
            button_L3.Text = "3";
            button_L3.UseVisualStyleBackColor = true;
            button_L3.Click += button_L3_Click;
            // 
            // button_L4
            // 
            button_L4.Location = new Point(295, 543);
            button_L4.Name = "button_L4";
            button_L4.Size = new Size(82, 72);
            button_L4.TabIndex = 8;
            button_L4.Text = "4";
            button_L4.UseVisualStyleBackColor = true;
            button_L4.Click += button_L4_Click;
            // 
            // label3
            // 
            label3.AutoSize = true;
            label3.Font = new Font("Microsoft YaHei UI", 18F);
            label3.Location = new Point(24, 211);
            label3.Name = "label3";
            label3.Size = new Size(128, 46);
            label3.TabIndex = 9;
            label3.Text = "电梯门";
            // 
            // Form1
            // 
            AutoScaleDimensions = new SizeF(11F, 24F);
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(925, 915);
            Controls.Add(label3);
            Controls.Add(button_L4);
            Controls.Add(button_L3);
            Controls.Add(button_L2);
            Controls.Add(button_L1);
            Controls.Add(label2);
            Controls.Add(textBox_door);
            Controls.Add(label1);
            Controls.Add(textBox_layer);
            Name = "Form1";
            Text = "Form1";
            ResumeLayout(false);
            PerformLayout();
        }

        #endregion

        private TextBox textBox_layer;
        private Label label1;
        private TextBox textBox_door;
        private Label label2;
        private Button button_L1;
        private Button button_L2;
        private Button button_L3;
        private Button button_L4;
        private Label label3;
    }
}

和案例二差不多,使用异步的方式 操作 楼层。

最大的区别是,案例二只有一个start按钮,而这里有多个楼层按钮

当同时按下多个按钮时,多个任务会同时运行,导致currentFloor被多个线程修改,引发竞态。

cs 复制代码
using System;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace lift
{
    public partial class Form1 : Form
    {
        private int currentFloor = 1; // 当前楼层
        private readonly object floorLock = new object(); 



        public Form1()
        {
            InitializeComponent();

        }



        private async Task LiftUp()//上升
        {
            if (currentFloor < 4)
            {
                await Task.Delay(2000);
                lock (floorLock)
                {
                    currentFloor++;
                }
                UpdateFloorDisplay();
            }
        }

        private async Task LiftDown()//下降
        {
            if (currentFloor > 1)
            {
                await Task.Delay(2000);
                lock (floorLock)
                {
                    currentFloor--;
                }
                UpdateFloorDisplay();
            }
        }

        private void UpdateFloorDisplay()
        {
            if (textBox_layer.InvokeRequired)
            {
                textBox_layer.BeginInvoke((Action)UpdateFloorDisplay);
                return;
            }
            textBox_layer.Text = currentFloor.ToString();
        }

        private async Task LiftRun(int targetFloor)//运行
        {
            while (currentFloor != targetFloor)
            {
                if (targetFloor > currentFloor)
                {
                    await LiftUp();
                }
                else
                {
                    await LiftDown();
                }
            }
            await OpenDoor();
        }

        private async Task OpenDoor()//开门
        {
            await Task.Delay(1000);
            if (textBox_door.InvokeRequired)
            {
                textBox_door.BeginInvoke((Action)(() => textBox_door.Text = "OPEN"));
            }
            else
            {
                textBox_door.Text = "OPEN";
            }

            await Task.Delay(2000);

            if (textBox_door.InvokeRequired)
            {
                textBox_door.BeginInvoke((Action)(() => textBox_door.Text = "CLOSE"));
            }
            else
            {
                textBox_door.Text = "CLOSE";
            }
        }

        private async void button_L1_Click(object sender, EventArgs e)
        {
            await LiftRun(1);
        }
        private async void button_L2_Click(object sender, EventArgs e)
        {
            await LiftRun(2);
        }
        private async void button_L3_Click(object sender, EventArgs e)
        {
            await LiftRun(3);
        }
        private async void button_L4_Click(object sender, EventArgs e)
        {
            await LiftRun(4);
        }


    }
}

为了解决多个按钮打架的问题。

我们只允许 一个事件在运行。

所以需要添加中断,后按的会中断之前的任务。

代码如下:

cs 复制代码
using System;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace lift
{
    public partial class Form1 : Form
    {
        private int currentFloor = 1; // 当前楼层
        private readonly object floorLock = new object();

        private CancellationTokenSource _cts;
        private readonly object _targetLock = new object();
        private int _targetFloor = 1;

        public Form1()
        {
            InitializeComponent();

        }


        private async Task LiftRun(CancellationToken token)
        {
            while (!token.IsCancellationRequested)
            {
                int currentTarget;
                lock (_targetLock)
                {
                    currentTarget = _targetFloor;
                }

                if (currentFloor == currentTarget)
                {
                    await OpenDoor();
                    return;
                }

                if (currentTarget > currentFloor)
                {
                    await LiftUp(token);
                }
                else
                {
                    await LiftDown(token);
                }
            }
        }

        // 修改后的上升方法
        private async Task LiftUp(CancellationToken token)
        {
            if (currentFloor < 4)
            {
                await Task.Delay(2000, token);  // 使用带取消令牌的延迟
                token.ThrowIfCancellationRequested();

                lock (floorLock)
                {
                    currentFloor++;
                }
                UpdateFloorDisplay();
            }
        }

        // 修改后的下降方法
        private async Task LiftDown(CancellationToken token)
        {
            if (currentFloor > 1)
            {
                await Task.Delay(2000, token);  // 使用带取消令牌的延迟
                token.ThrowIfCancellationRequested();

                lock (floorLock)
                {
                    currentFloor--;
                }
                UpdateFloorDisplay();
            }
        }



        private async Task OpenDoor()//开门
        {
            await Task.Delay(1000);
            if (textBox_door.InvokeRequired)
            {
                textBox_door.BeginInvoke((Action)(() => textBox_door.Text = "OPEN"));
            }
            else
            {
                textBox_door.Text = "OPEN";
            }

            await Task.Delay(2000);

            if (textBox_door.InvokeRequired)
            {
                textBox_door.BeginInvoke((Action)(() => textBox_door.Text = "CLOSE"));
            }
            else
            {
                textBox_door.Text = "CLOSE";
            }
        }

        // 统一处理楼层请求的方法
        private async Task HandleFloorRequest(int requestedFloor)
        {
            // 更新目标楼层
            lock (_targetLock)
            {
                _targetFloor = requestedFloor;
            }

            // 取消当前运行的任务
            _cts?.Cancel();

            // 创建新的取消令牌
            var newCts = new CancellationTokenSource();
            _cts = newCts;

            try
            {
                await LiftRun(newCts.Token);
            }
            catch (OperationCanceledException)
            {
                // 正常取消,无需处理
            }
        }



        private async void button_L1_Click(object sender, EventArgs e)
        {
            await HandleFloorRequest(1);
        }

        private async void button_L2_Click(object sender, EventArgs e)
        {
            await HandleFloorRequest(2);
        }

        private async void button_L3_Click(object sender, EventArgs e)
        {
            await HandleFloorRequest(3);
        }

        private async void button_L4_Click(object sender, EventArgs e)
        {
            await HandleFloorRequest(4);
        }




        private void UpdateFloorDisplay()
        {
            if (textBox_layer.InvokeRequired)
            {
                textBox_layer.BeginInvoke((Action)UpdateFloorDisplay);
                return;
            }
            textBox_layer.Text = currentFloor.ToString();
        }





    }
}

运行后:

屏幕录制 2025-08-11 112753

显然,视频中,后按的按钮直接打断了之前的任务。

为了能像现实中的电梯一样有序,进行改进:

cs 复制代码
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace lift
{
    public partial class Form1 : Form
    {
        private int currentFloor = 1;
        private readonly object stateLock = new object();
        private readonly SortedSet<int> upRequests = new SortedSet<int>();
        private readonly SortedSet<int> downRequests = new SortedSet<int>(Comparer<int>.Create((x, y) => y.CompareTo(x)));
        private bool isMoving = false;
        private bool doorOpen = false;

        public Form1()
        {
            InitializeComponent();
            UpdateDisplay();
        }

        private void UpdateDisplay()
        {
            if (textBox_layer.InvokeRequired)
            {
                textBox_layer.BeginInvoke((Action)UpdateDisplay);
                return;
            }

            textBox_layer.Text = currentFloor.ToString();
            textBox_door.Text = doorOpen ? "OPEN" : "CLOSE";
        }

        private async Task ElevatorLoop()
        {
            while (true)
            {
                int nextFloor = GetNextDestination();

                if (nextFloor == -1)
                {
                    isMoving = false;
                    await Task.Delay(100);
                    continue;
                }

                isMoving = true;
                await MoveToFloor(nextFloor);
                await HandleStop(nextFloor);
            }
        }

        private int GetNextDestination()
        {
            lock (stateLock)
            {
                // 优先处理当前楼层的请求
                if (upRequests.Contains(currentFloor) || downRequests.Contains(currentFloor))
                {
                    return currentFloor;
                }

                // 根据当前方向选择下一个目标
                if (upRequests.Count > 0)
                {
                    return upRequests.Min;
                }

                if (downRequests.Count > 0)
                {
                    return downRequests.Max;
                }

                return -1; // 无请求
            }
        }

        private async Task MoveToFloor(int targetFloor)
        {
            while (currentFloor != targetFloor)
            {
                await Task.Delay(1000); // 移动时间缩短为1秒便于测试

                lock (stateLock)
                {
                    if (currentFloor < targetFloor)
                    {
                        currentFloor++;
                    }
                    else
                    {
                        currentFloor--;
                    }
                }

                UpdateDisplay();

                // 检查移动过程中是否有同方向的中间请求
                await CheckIntermediateStops();
            }
        }

        private async Task CheckIntermediateStops()
        {
            lock (stateLock)
            {
                // 如果是上行且当前楼层有上行请求
                if (upRequests.Contains(currentFloor))
                {
                    // 临时移除请求,会在HandleStop中重新添加
                    upRequests.Remove(currentFloor);
                }
                // 如果是下行且当前楼层有下行请求
                else if (downRequests.Contains(currentFloor))
                {
                    downRequests.Remove(currentFloor);
                }
                else
                {
                    return;
                }
            }

            // 立即处理当前楼层的请求
            await HandleStop(currentFloor);
        }

        private async Task HandleStop(int floor)
        {
            // 开门
            doorOpen = true;
            UpdateDisplay();
            await Task.Delay(1500); // 开门时间

            // 处理当前楼层的所有请求
            lock (stateLock)
            {
                upRequests.Remove(floor);
                downRequests.Remove(floor);
            }

            // 关门
            doorOpen = false;
            UpdateDisplay();
            await Task.Delay(1000); // 关门时间

            // 重新评估方向
            EvaluateDirection();
        }

        private void EvaluateDirection()
        {
            lock (stateLock)
            {
                // 如果没有请求了,保持静止
                if (upRequests.Count == 0 && downRequests.Count == 0)
                {
                    isMoving = false;
                    return;
                }

                // 如果有上行请求在当前楼层之上,或下行请求在当前楼层之下
                isMoving = (upRequests.Count > 0 && upRequests.Min > currentFloor) ||
                          (downRequests.Count > 0 && downRequests.Max < currentFloor);
            }
        }

        private void AddRequest(int floor)
        {
            if (floor < 1 || floor > 4)
            {
                MessageBox.Show("无效楼层请求");
                return;
            }

            lock (stateLock)
            {
                // 根据当前位置和方向决定将请求加入哪个队列
                if (floor > currentFloor)
                {
                    upRequests.Add(floor);
                    downRequests.Remove(floor); // 确保请求不在两个队列中
                }
                else if (floor < currentFloor)
                {
                    downRequests.Add(floor);
                    upRequests.Remove(floor);
                }
                else
                {
                    // 当前楼层的请求立即处理
                    upRequests.Add(floor); // 随便加一个队列,会在HandleStop中处理
                }

                // 如果电梯静止,启动它
                if (!isMoving && !doorOpen)
                {
                    Task.Run(ElevatorLoop);
                }
            }
        }

        private void button_L1_Click(object sender, EventArgs e) => AddRequest(1);
        private void button_L2_Click(object sender, EventArgs e) => AddRequest(2);
        private void button_L3_Click(object sender, EventArgs e) => AddRequest(3);
        private void button_L4_Click(object sender, EventArgs e) => AddRequest(4);
    }
}