当前位置: 代码迷 >> C# >> UI操作耗时太长有什么办法吗,该怎么解决
  详细解决方案

UI操作耗时太长有什么办法吗,该怎么解决

热度:38   发布时间:2016-05-05 03:31:44.0
UI操作耗时太长有什么办法吗
我的程序用于监视几十个下位机的数据,按照要求主界面上要根据每个下位机的数据显示不同的图片,例如报警就显示红色图片。所以我做了个usercontrol,上面就是一个label一个picturebox一个tooltip,其中tooltip是用来当鼠标移动到图片上时显示几个重要的下位机数据。
然后在主界面动态加载几十个这种usercontrol,然后每秒钟根据当前数据刷新界面。现在的问题是,每更新一次界面要花2秒甚至3秒时间,系统时间显示总是每次蹦几秒,鼠标移动显示tooltip也有明显卡顿。
求助高手。


我这么写的
private void main(object sender, EventArgs e)
{
Thread thread_1s=new Thread(new ThreadStart(UI_callback));
thread_1s.IsBackground=true;
thread_1s.Start();
}
private void UI_callback()
{
while(true)
{
this.BeginInvoke(new EventHandler(RefreshUI),null);
Thread.Sleep(1000);
}
private void RefreshUI(object sender, EventArgs e)
{
toolStripStatusLabelTime.Text=DateTime.Now.Tostring();

//根据当前数据刷新界面,例如if(alarms[Station.Id].Count>0){pictureBox1.Image=imageList1.Images[3];}
}

------解决思路----------------------
为什么要显示 红色 图片 ,可以用一个label 让后改变它的Background。

蹦几秒 是因为 你加了 Thread.Sleep(1000);
------解决思路----------------------
引用:
...
然后在主界面动态加载几十个这种usercontrol,然后每秒钟根据当前数据刷新界面。
...

我这么写的
private void main(object sender, EventArgs e)
{
Thread thread_1s=new Thread(new ThreadStart(UI_callback));
thread_1s.IsBackground=true;
thread_1s.Start();
}


是每个UserControl执行一个main(object sender, EventArgs e)吗?
如果是,有几十个UserControl就会有几十个UI_callback线程,它们将互相竞争。

建议你只在主窗口用一个定时器,定时刷新各个UserControl。
定时器用System.Windows.Forms.Timer,不需要另外BeginInvoke.
------解决思路----------------------
以下例子用了40个UserControl,每秒刷新。
建议你新建一个WinForm项目,拷贝例子代码,替换掉Form1类,即可编译运行。


public partial class Form1 : Form
{
    public Form1()
    {
        FlowLayoutPanel panel = new FlowLayoutPanel() { Padding = new Padding(8), Dock = DockStyle.Fill };
        for (int i = 0; i < 40; i++)
        {
            myUserControlList.Add(new MyUserControl());
            panel.Controls.AddRange(myUserControlList.ToArray());
        }
        this.Controls.Add(panel);
        timer.Tick += timer_Tick;
        timer.Start();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        foreach (MyUserControl myControl in myUserControlList)
        {
            MyData data = new MyData() { Description = DateTime.Now.Second.ToString(), Status = random.Next(3) };
            myControl.Update(data);
        }
    }

    Random random = new Random();
    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer() { Interval = 1000 };
    List<MyUserControl> myUserControlList = new List<MyUserControl>();

    class MyData
    {
        public string Description { get; set; }
        public int Status { get; set; }
    }
    class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            this.Controls.AddRange(new Control[] { label, pictureBox });
            this.Size = new Size(60, 30);
        }

        public void Update(MyData data)
        {
            label.Text = data.Description;
            pictureBox.Image = images[data.Status % images.Length];
        }

        Label label = new Label() { Width = 30 };
        PictureBox pictureBox = new PictureBox() { Location = new Point(30, 0), };
        static Image[] images = new Image[] { SystemIcons.Warning.ToBitmap(), SystemIcons.Question.ToBitmap(), SystemIcons.Information.ToBitmap() };
    }
}

------解决思路----------------------
上面的回帖我没看,或许我的回复有重复,特此先说明一下。

看了一眼你的代码,它实在是太“坑爹”了啊。你的代码
Thread thread_1s=new Thread(new ThreadStart(UI_callback));
thread_1s.IsBackground=true;
thread_1s.Start();
}
private void UI_callback()
{
while(true)
{
this.BeginInvoke(new EventHandler(RefreshUI),null);
Thread.Sleep(1000);
}


这里,你弄一个线程在那里“玩儿cpu”,让它循环着(本身线程上下文相关数据结构要占用资源,它还抢占其它线程的CPU调度资源),目的是干什么呢?只是为了向主线程注册一个 RefreshUI 方法么?并且你的 RefreshUI 方法也还都是在主线程排队执行的。

.net的Timer比你自己写的线程死循环要高效得多得多。就算是你使用最低级的Timer(.net至少共有3种或者4种Timer),使用它的代码比你写的线程代码更清晰。你的这种程序根本用不着什么线程的。就像刚学编程的人一样学会拖一个Timer控件到设计画面上,就比你的代码还要好。
------解决思路----------------------
几十字不卡才怪。这个没有解决办法。你网上搜一下,出现这个问题的很多。换一种显示方式吧。
  相关解决方案