解决方案 »

  1.   

    label是显示给用户看的
    50ms刷新一次有什么意义么?
    即使数据在50ms之内有变化,你确实实时的显示出来了,用户能看的过来么?
    改成500ms完全没有任何区别的.
      

  2.   

    或者你在赋值之前先判断一下
    if(lable1.text!=value)
    {
    lable1.text=value;
    }
      

  3.   

    我也知道50ms更新一次,人根本看不清楚。但是用户表明这个是硬需求,可以看到树枝的线性波动情况现实情况是,需求没办法改变,就只能自己想办法解决
    用列表控件不行么?= =用300个label想当蛋疼。。如果是listview 或者 datagridview的话300条数据完全没有问题。
      

  4.   

    数据来源是单片机,单片机数据来源是采集器,采集器是50ms采集一次工作环境数据然后发送。我也不知道这50ms对于观察有什么意义,1秒钟20帧看电影啊但是换成数字能看得过来么。数据的话,95%每次都会有变化,所以全部更新和比较是否有变化再更新,没太大区别
      

  5.   

    说一下软件的界面情况:
    一个form均分为20块区域,每块上有15个label控件。每一块区域对应一台采集器采集的数据。程序就是要把这20台采集器的数据更新到界面上。采集器和程序之间通过RJ45连接,Form做socket的server,采集器是client。通讯、数据解包分析什么的,几乎不占时间,时间全部都耗在了更新UI上
      

  6.   

    可以试试多开几个线程吧,每个线程依次对主窗体线程部分控件进行刷新,同时只有1个线程启动,其他都是阻塞状态,这样应该能达到伪全部刷新的效果吧。
    PS:50ms要求肯定太BT了
      

  7.   


    就是一般的socket 一对多server的写法。
    监听线程获取到新的连接,就新开一个线程用while(true)去获取通讯数据,然后解包,更新UI。
      

  8.   


    仅有部分label的数据可以看到变化,绝大多数的都不动(实际上数值是有变化的),能变化的Label是随机的,不一定是哪些,有可能这几秒是某些,下几秒是另一些。但是数据通讯正常,数据并没有丢失,将数据连断开后,会发现所有的label都会被更新到最新的数据。如果降低这个50ms的要求,目前测试出来是400ms,那么可以到所有的label都顺利的同时发生变化。
      

  9.   


    。HTML不是问题,问题是:HTML如何做socket通讯?
      

  10.   

    试了一下,好像没有问题public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }        private void Form1_Load(object sender, EventArgs e)
            {
                CreateLabel();
            }        Hashtable ht = new Hashtable();
            int Seed = 0;
            int dis = 5;
            bool auto = false;
            int row = 10;
            int col = 30;        void CreateLabel()
            {
                for (int i = 0; i < col; i++)
                {
                    for (int j = 0; j < row; j++)
                    {
                        Label lb = new Label();
                        lb.Name = "lb" + i.ToString() + j.ToString();
                        lb.Width = 30;
                        lb.Height = 15;
                        lb.Text = "lbl";
                        lb.Location = new Point(lb.Width * i + dis, lb.Height * j + dis);
                        lb.Parent = panel1;
                        lb.Show();                    ht.Add(lb.Name, lb);
                    }
                }
            }
            int[,] GetValues()
            {
                int[,] vals = new int[col, row];            for (int i = 0; i < col; i++)
                {
                    for (int j = 0; j < row; j++)
                    {
                        long tick = DateTime.Now.Ticks;
                        Random rd = new Random(Seed);
                        vals[i, j] = rd.Next(1, 100);                    Seed++;
                        while (Seed == int.MaxValue)
                        {
                            Seed = 0;
                        }
                    }
                }            return vals;
            }        void Refresh()
            { 
                int[,] vals = new int[col, row];
                vals = GetValues();            for (int i = 0; i < col; i++)
                {
                    for (int j = 0; j < row; j++)
                    {
                        Update("lb" + i.ToString() + j.ToString(), vals[i, j]);
                    }
                } 
            }        delegate void delUpdate(string name, int val);
            void Update(string name, int val)
            {
                Label lb = ht[name] as Label;
                if (lb.InvokeRequired)
                {
                    delUpdate du = new delUpdate(Update);
                    lb.Invoke(du, new object[] { name,val});
                         
                }
                else
                {
                    lb.Text = val.ToString();
                }
            }
            void AutoRefresh()
            {
                while (auto)
                {
                    Refresh();
                    Thread.Sleep(50);
                }
            }
            private void btnManaul_Click(object sender, EventArgs e)
            {
                Refresh();
            }        private void btnStart_Click(object sender, EventArgs e)
            {
                Thread thd = new Thread(new ThreadStart(AutoRefresh));
                auto = true;
                thd.Start();
            }        private void btnEnd_Click(object sender, EventArgs e)
            {
                auto = false;
            }
        }
      

  11.   

    明白了.
    目测是加锁加的有问题.
    导致某个线程在操作UI的时候,其他线程无法将数据更新到UI.
      

  12.   

    另外,你的这个多线程目测根本不需要加锁.
    多线程将数据写入同一个全局数组中
    然后主线程(可以是timer)就循环到数组中取数据显示就好了.或者要加锁也应该是每个线程使用不同的锁(因为每个线程其实是对数组中的不同元素在进行更新)
    不要都统一使用一个锁,会造成一个线程在写入数据的时候,其他线程无法写入对应的其他数据
      

  13.   

    昨天最后的尝试就是这样,多线程,将数据写入一个全局的数组,主线程新开一个Thread.Timer,100ms刷新一次这些数据到UI。这个Timer里第一次尝试使用了个一个for,来循环20块区域,后来修改为逐条语句写出来,实测均无改善。要想达到“流畅”的感觉,仍然需要400ms左右。
      

  14.   

    用您的代码测试了下,的确没有问题!奇怪的是,按我的方法测试了下,300个Label更新也没问题。
    后来琢磨了下,貌似问题出在UI上!测试的代码,ui很简单,纯净的背景,什么都没有,问题是,真实程序的UI不能说花哨,但是每一个区块(总共20个区块,布局、用色相同)都有不同的背景颜色对数据进行了区分,这时候,效率就下来!用你的代码,panel上加了张背景图上去,立刻挂了。
      

  15.   

    我勒个去啊!!!!!问题找到了,果然和UI有关系!17楼同学很热心的发了测试代码,我测试了下果然300个Label的更新不算事儿,于是想到测试界面没有实际界面那么复杂,于是加了张背景图,顺手把label的backgroundcolor指定为:Color.Transparent,于是,程序果然挂了!!!立马把Transparent注释掉,又正常了!看来Transparent相当耗费系统资源。准备找美工改Ui去,放弃渐变色等背景,全部改为纯色块,这样label就可以指定color而不用Transparent了。表示下无语。。
    感谢17楼同学提供测试代码,看来碰到问题还是要简化后测试,很快就定位到援引了。写成需时间长了,人变懒了感谢其余同学的帮助。结帖
      

  16.   


    找到问题了。Color.Transparent我勒个去。。严重影响性能啊
      

  17.   


    找到问题了。Color.Transparent我勒个去。。严重影响性能啊
    呵呵,解决了就好.
      

  18.   

    不应该,我做过一个工艺图的展示实时更新的程序,也遇到过类似的问题,好像重写OnPaint方法,使用多线程局部刷新数据,背景都是金属色的背景图,大小也有几十个,更新数据的Label也有近百个吧,都没有问题的
      

  19.   


    可否借鉴下How to do?
      

  20.   

    那么多lable为什么不能弄成关联性的 然后用一个控件自己绘制  一次刷新一批  每次刷新一次底图 然后绘制上数据就行了撒. 50ms刷新1024*800的屏幕应该可以的
      

  21.   


    每15个label为一组,是一个相同的数据源。不知道您说得自己绘制怎么做?另外,分辨率是1920*1080
      

  22.   

    意思用17楼代码已经可以了吗?
    如果还不行,试试下面三个函数呢
      this.SuspendLayout();
      this.ResumeLayout(false);
                this.PerformLayout();
    这三个函数或许对你有帮助。
    申明:我没有测试过
      

  23.   

    不要用label作输出
    直接在onpaint里面自己把所有数据画出来
      

  24.   

    你所需要做的,就是用两个数组
    一个保存数据、另一个保存输出坐标
    在OnPaint里面,循环坐标输出数据C#具体操作我不知道
    但是有个API函数(SetBkMode)可以在输出字符前,把整个绘图场景的输出字符背景设透明
    只需设置一次就行了50ms,足够画背景+300次字符输出了
      

  25.   

        CPaintDC dc(this);    CRect rcClt;
        GetClientRect(&rcClt);    int cx = rcClt.Width();
        int cy = rcClt.Height();// 使用双缓冲绘图,避免画面闪烁
        CBitmap bmp;
        bmp.CreateCompatibleBitmap(&dc, cx, cy);
        CDC memDC;
        memDC.CreateCompatibleDC(&dc);
        memDC.SelectObject(&bmp);    CFont font;
        font.CreateFont(-12, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, 0, 0, L"宋体");
        memDC.SelectObject(&font);    int nFontWidth = cx / 10;    memDC.SetTextColor(RGB(0, 0, 255)); // 设置文字颜色
        memDC.SetBkMode(TRANSPARENT); // 设置输出文字背景透明    DWORD dwTimeStart = ::GetTickCount();    for (int i = 0; i < 1000; i++)
        {
            memDC.FillSolidRect(&rcClt, RGB(255, 0, 0));        CRect rcText(-nFontWidth, 0, 0, 12);
            for (int j = 0; j < 300; j++)
            {            if ((j % 15) == 0)
                {
                    rcText.top = 0;
                    rcText.bottom = 12;
                    rcText.OffsetRect(nFontWidth, 0);
                }            TCHAR szText[32];
                ::wsprintf(szText, L"Test%d", j + 1);            memDC.DrawText(szText, -1, &rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
                rcText.OffsetRect(0, 12);
            }
        }    TRACE1("Used time: %d\n", ::GetTickCount() - dwTimeStart);    dc.BitBlt(0, 0, cx, cy, &memDC, 0, 0, SRCCOPY);这是刚写的MFC代码
    循环1000次只用了4571毫秒
    除去每次计算坐标的代码,还可以再节省一点
    代码里我没有用背景图,只是简单的画了个背景色
    但是按照我以前使用的经验,画一副1080P的图片用时也不会很久
      

  26.   


    每15个label为一组,是一个相同的数据源。不知道您说得自己绘制怎么做?另外,分辨率是1920*1080一次把一组的数据自己按坐标绘制上去. 毕竟你每次都要全部刷新这样节省了大量的绘制消息和背景的刷新
      

  27.   


    额。vs2010里 this.后面提示不了你说的这三个,是不是要引用什么?
      

  28.   


    额。vs2010里 this.后面提示不了你说的这三个,是不是要引用什么?我可以点出来呢你随便建一个winform,在design.cs里面都有的
      

  29.   

    Label显示消息在少量的时候适合,我最近也在做一些上位机的东西,面对众多label串口都已经关闭了页面还在刷新。
    由于我们只是要显示一句话或者一个值,而Label本身封装了很多属性在里面,而且具体是什么也不甚了解。那么简单原则,自己写一个Control来替代label即可。
    我是这样解决的public sealed partial class SuperLabel : Control
        {
            public SuperLabel()
            {
                this.DoubleBuffered = true;
            }        protected override void OnPaintBackground(PaintEventArgs e)
            {
                if (this.DesignMode)
                {
                    base.OnPaintBackground(e);
                }
            }        protected override void OnTextChanged(EventArgs e)
            {
                base.OnTextChanged(e);
                Refresh();
            }        protected override void OnPaint(PaintEventArgs e)
            {
                base.OnPaint(e);
                StringFormat format = new StringFormat {LineAlignment = StringAlignment.Center};
                e.Graphics.FillRectangle(new SolidBrush(BackColor), this.ClientRectangle);
                e.Graphics.DrawString(this.Text, this.Font,new SolidBrush(ForeColor), this.ClientRectangle, format);
            }
        }