在线程中更新UI

为了更新UI线程,在新线程中用this.Invoke来更新UI上控件的值。

其实这背后是有异常的(有可能会在vs中报出来),因为当你关闭窗体时,this已经不存在了,但访问this.Invoke在新的线程中,新线程本身并没有关掉,这时就会报找不到实例而引发报错。

有可能运行起来并不会发现异常,这是因为主线程关闭后,所有创建的子线程都会关闭的。

 

解决方案:

方法1:

参考:Timer控件-Forms.Timer\System.Timers.Timer\System.Threading.Timer - hanzq_go - 博客园 (cnblogs.com)

        private void FormTimer1_FormClosed(object sender, FormClosedEventArgs e)
        {
            System.Environment.Exit(0);//结束进程
        }

 

方法2:

通过一个mark标志,在关闭窗体时,拦截一下,把子线程关闭,然后再把主窗体关闭,这样就没有问题了,自己起的线程,自己要关掉。

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
            this.FormClosing += Form1_FormClosing;
            
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (mark)
            {
                e.Cancel = true;
                mark = false;
            }
        }

        static List<Item> list;
        private void Form1_Load(object sender, EventArgs e)
        {
            list = new List<Item>
            {
                new Item{ Name="正在上传诊疗项目",Time=8 },
                new Item{ Name="正在上传器材",Time=10 },
                new Item{ Name="正在上传药品",Time=10 },
                new Item{ Name="正在核对",Time=12 }
            };
        }
        static bool mark;
        private void button1_Click(object sender, EventArgs e)
        {
            mark = true;
            Task.Run(() =>
            {
                foreach (var item in list)
                {
                    if (mark == false)
                    {
                        break;
                    }
                    var dotString = "";
                    for (var i = 0; i < item.Time; i++)
                    {
                        if (mark == false)
                        {
                            break;
                        }
                        if (i % 6 == 0)
                        {
                            dotString = ".";
                        }
                        else
                        {
                            dotString += ".";
                        }
                        this.Invoke(new Action(() => messageLabel.Text = $"{item.Name}{dotString}"));
                        Thread.Sleep(100);
                    }
                }
                //MessageBox.Show("完成医保所有数据同步");
                if (mark)
                {
                    mark = false;
                    MessageBox.Show("完成医保所有数据同步");
                }
                else
                {
                    this.Invoke(new Action(() => { this.Close(); }));
                }

            });
        }
    }
}

 

posted on 2022-10-24 15:04  hanzq_go  阅读(84)  评论(0编辑  收藏  举报

导航