WinForm——Software loading and reading interface stuck problem


Preface

When the production software opens the interface and loads the reading article, a new Loading form is created in the Program, but it is found that the form is displayed but the controls in the interface do not follow the changes, and even freezes, so analyze the cause, and find a solution.


1. Problem phenomenon

normal circumstances:
insert image description here

Situation 1: (setting the text through the Set written by myself in the Form)
insert image description here
Situation 2: (writing the text automatically through the Form timer cycle)
insert image description here
Situation 3: (writing the text through the custom thread cycle in the Form)
insert image description here

2. Test part of the code

1.Loading form

code show as below:

        public FrmLoading()
        {
    
    
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterScreen;
        }


        public void SetPercentVal(int val,string message)
        {
    
    
            this.Invoke(new Action(() =>
            {
    
    
                this.SuspendLayout();
                pgb_1.Value = val;
                //lb_Percent.Text = "%" + pgb_1.Value;
                //lb_Message.Text = message;
                this.ResumeLayout();
            }));
        }

        private void FrmLoading_Load(object sender, EventArgs e)
        {
    
    
            Thread thread = new Thread(a);
            thread.IsBackground = true;
            thread.Start();

            //this.DoubleBuffered = true;
            timer1.Enabled = true;
        }

        void a() 
        {
    
    
            while (true)
            {
    
    
                this.Invoke(new Action(() =>
                {
    
    
                    lb_Percent.Text = "%" + pgb_1.Value;

                }));

            }
            //lb_Message.Text = Meaagae;

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
    
    
            //if (pgb_1.Value == 100)
            //{
    
    
            //    if (this.InvokeRequired)
            //    {
    
    
            //        this.Invoke((Action)this.Close);
            //    }
            //    else
            //    {
    
    
            //        this.Close();
            //    }
            //}
            //else
            //{
    
    
            //    lb_Percent.Text = "%" + pgb_1.Value;
            //    //lb_Message.Text = Meaagae;
            //}
        }

2. Load the code Program

code show as below:

        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
    
    
            LogHelper.WriteInfo("------------------------------------------------");
            LogHelper.WriteInfo("软件启动。");
            LogHelper.WriteInfo("------------------------------------------------");

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            
            Global_Value.G_LoadingFrm = new UI_Frm.FrmLoading();
            Global_Value.G_LoadingFrm.Show();

            while (Global_Value.G_LoadingFrm == null || !Global_Value.G_LoadingFrm.Visible)
            {
    
    
                System.Threading.Thread.Sleep(100);
            }

            //初始化
            Global_Method.Ini();

            Global_Value.G_LoadingFrm.SetPercentVal(90, "初始化界面");

            Global_Value.G_MainFrm = new FrmMain();
            Global_Value.G_MainFrm.Visible = true;

            Global_Value.G_LoadingFrm.SetPercentVal(100, "加载完成");
			Global_Value.G_LoadingFrm.Close();
			
            Application.Run(Global_Value.G_MainFrm);
        }


3. Analyze the reasons

Taking the Timer version as an example, in a C# Windows Forms application, the Tick event of the Timer component will be triggered on the UI thread. This means that when the Application.Run method is called to start the main message loop, the UI thread starts processing the messages of the form and controls, and triggers the Tick event of the Timer component.
If you first create the form and start the timer in the Main method of the Program class, and then call Application.Run, the UI thread will not fire the Tick event because the main message loop has not yet started, so the event handler will not execute.
The other two situations are also similar, and they are also caused by not enabling the message loop, and the text is not new and stuck. So there is the following solution.

4. Solution code

Open the message loop when the Loading interface starts, and close it after it ends.
The specific optimization code (part) is as follows:

1.Loading form

code show as below:

    public partial class FrmLoading : Form
    {
    
    
        public FrmLoading()
        {
    
    
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterScreen;
        }


        public void SetPercentVal(int val,string message)
        {
    
    
            this.Invoke(new Action(() =>
            {
    
    
                pgb_1.Value = val;
                lb_Percent.Text = "%" + pgb_1.Value;
                lb_Message.Text = message;
            }));
        }

        private void FrmLoading_Load(object sender, EventArgs e)
        {
    
    
            timer1.Enabled = true;
        }


        private void timer1_Tick(object sender, EventArgs e)
        {
    
    
            if (pgb_1.Value == 100)
            {
    
    
                if (this.InvokeRequired)
                {
    
    
                    this.Invoke((Action)this.Close);
                }
                else
                {
    
    
                    this.Close();
                }
            }
        }
    }

2. Load the code Program

code show as below:

        static void Main()
        {
    
    
            LogHelper.WriteInfo("------------------------------------------------");
            LogHelper.WriteInfo("软件启动。");
            LogHelper.WriteInfo("------------------------------------------------");

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            var loadingFormThread = new System.Threading.Thread(ShowLoadingForm); // 创建加载界面线程
            loadingFormThread.Start(); // 启动加载界面线程

            while (Global_Value.G_LoadingFrm == null || !Global_Value.G_LoadingFrm.Visible)
            {
    
    
                System.Threading.Thread.Sleep(100);
            }

            //初始化
            Global_Method.Ini();


            Global_Value.G_LoadingFrm.SetPercentVal(90, "初始化界面");

            Global_Value.G_MainFrm = new FrmMain();
            Global_Value.G_MainFrm.Visible = true;

            Global_Value.G_LoadingFrm.SetPercentVal(100, "加载完成");

            loadingFormThread.Join();//等待加载界面结束
            Application.Run(Global_Value.G_MainFrm);
        }

        private static void ShowLoadingForm()
        {
    
    
            Global_Value.G_LoadingFrm = new UI_Frm.FrmLoading();
            Application.Run(Global_Value.G_LoadingFrm);
        }
    }

Guess you like

Origin blog.csdn.net/qq_42504097/article/details/131190910