首页 新闻 会员 周边

winform 毫秒级更新datagridview问题!!!!! 在线等!!!!!!

0
悬赏园豆:5 [已关闭问题] 解决于 2012-11-27 18:26

简化了程序的逻辑,最大程度让大家明白我的意思!

 

程序功能:

每一行是一个button,当点击button后,通过 ThreadPool.QueueUserWorkItem,AutoResetEvent  去调用SetMessage 方法。

SetMessage方法返回当前的时间!

然后更新所在行的button的text 为  当前时间

 

 

 

程序效果图:

 

 

 

 

点击每一行的button后就等待更新 button的text

 

 

 

 

问题:   

       毫秒级别的更新会让 datagridview  卡卡的,我实际的程序就要求毫秒级别的更新。

 

       

       可能你会说,改成5秒一更新就会不卡了,这样我也知道,可是程序需要的就是毫秒级别更新!!

 

 

 

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using common;
using System.Threading;
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {



            //获取 button 行列号
            int selectColumn = this.dataGridView1.CurrentCell.ColumnIndex;    //lie
            int selectRow = this.dataGridView1.CurrentCell.RowIndex;


                MyAsync a = new MyAsync();
                a.i = selectColumn;
                a.j = selectRow;

                AutoResetEvent asyncOPIsDone = a.asyncOPIsDone;

               
                ThreadPool.QueueUserWorkItem(new WaitCallback(myAsync), a);
          





        }



        public void myAsync(object state)
        {

            int col = ((MyAsync)state).i;
            int row = ((MyAsync)state).j;


            //循环更新  button 的text 
            while (true)
            {
                ((MyAsync)state).SetMessage("now:");
                dataGridView1[col, row].Value = ((MyAsync)state).message;

            }

            ((MyAsync)state).asyncOPIsDone.Set();
           

        }


 

     

        /// <summary>
        /// datagridvie增加一行。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void addRow_Click(object sender, EventArgs e)
        {

            Button btn=new Button();


            this.dataGridView1.Rows.Add(btn);
        }

    }
}

 

 

 

 public class MyAsync
    {



        public AutoResetEvent asyncOPIsDone = new AutoResetEvent(false);
        public string message;
        public int i;                                                       //column number
        public int j;                                                       //row  number
       
       


        public  void SetMessage(string strState)
        {
           message = strState + DateTime.Now.ToString("HH:mm:ss.fff");
        }


     
    }

 

 

 

 

 

 目前这样的毫秒级更新,当行多了,就会感觉卡!

 

 

更新:

总结了下大家的方法,多数都在说 控件重绘太耗资源了。

 

要自己去绘制!  自己绘制参考哪些知识呢?  


   

水墨.MR.H的主页 水墨.MR.H | 菜鸟二级 | 园豆:280
提问于:2012-05-03 09:04
< >
分享
其他回答(4)
0

自己绘制~

控件重绘太耗资源。

Andrew.Wangxu | 园豆:211 (菜鸟二级) | 2012-05-03 09:35
0

关注~

Philomena | 园豆:154 (初学一级) | 2012-05-03 09:54
1

你用死循环去不停刷新,不卡才怪。你用个timer,每毫秒更新一次,不就行了。

水牛刀刀 | 园豆:6350 (大侠五级) | 2012-05-03 10:13

毫秒你可以试试,用timer一样的卡!

 

找到问题所在了,是界面重绘卡。

 

与你说的timer完全无关

支持(0) 反对(0) 水墨.MR.H | 园豆:280 (菜鸟二级) | 2012-05-03 11:17

@水墨.MR.H: 你花2分钟自己跑个例子试试,新建一个winform程序,拖3个button(button1到button3),再拖一个timer,把timer的Interval属性设置成1,然后在timer的Tick事件里:

        private void timer1_Tick(object sender, EventArgs e)
        {
            button1.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff");
            button2.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff");
            button3.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff");
        }

我刚试过了,毫无压力。

支持(0) 反对(0) 水牛刀刀 | 园豆:6350 (大侠五级) | 2012-05-03 11:54

@水墨.MR.H: 我又试了下拖了10个button,毫无卡的迹象。如果你的程序卡,那一定是别的地方出了问题。

支持(0) 反对(0) 水牛刀刀 | 园豆:6350 (大侠五级) | 2012-05-03 11:57

@水牛刀刀: 谢谢! 找到主要问题了,while(ture)  这个太耗资源了。

 

  加上 Thread.sleep(1) 就好多了。

public void SetMessage(string strState)
{
message = strState + DateTime.Now.ToString("HH:mm:ss.fff");

Thread.sleep(1); 
}

 

 

虽然看起来和timer 的 1毫秒 差不多,但是 消耗CPU资源远远小于 timer

因为timer 都是主线程在运算当前时间,而threadpool 只是重新赋值时候用到了主线程及UI线程。

 

 

 

不过,很谢谢你!

支持(0) 反对(0) 水墨.MR.H | 园豆:280 (菜鸟二级) | 2012-05-03 15:54

@水墨.MR.H: Thread.Sleep(1)暂停了1毫秒,实际算上上面程序执行的时间(非常短,小于1毫秒),那么你的button上的时间不是1毫秒刷新一次,而是1.xxxx毫秒刷新一次。不过估计也能接受了。

支持(0) 反对(0) 水牛刀刀 | 园豆:6350 (大侠五级) | 2012-05-03 16:18

@水牛刀刀: 是的!

不过从CPU占用率来说, timer 太弱了,依靠主线程去计算。

还是委托其他线程计算,主线程只用来更新控件吧

支持(0) 反对(0) 水墨.MR.H | 园豆:280 (菜鸟二级) | 2012-05-03 16:36
0

1.按毫秒级别来更新的时候,你为什么要显示那么多行? 你都精确到毫秒级别了,人的眼睛能同时看几行? 大部分记录都可以记录下来,等人去查看。只有实时给人看的拿一小部分才需要刷到UI上去。

2.自己绘制控件请参考GDI+有关的内容。自己用GDI+绘制控件确实可以解决性能问题,但是如果你以前没做过,短时间内是不会解决你的性能问题的。先不考虑性能,一周之内自己能把控件丑陋地绘制出来就很不错了。

太初有道 | 园豆:206 (菜鸟二级) | 2012-05-06 10:00
0

大量数据或者显示要求及时的地方你可以使用下面的思路:

1、数据源和数据视图要分离

2、假定你的表格控件最多能显示40行,那么你可以通过只显示40行进行刷新。

3、假如你的数据超过40行,那么只绑定40行的视图。(因为你要及时,毫秒级的,人眼是看不过来的。人如果想看详细的,弄个其他的表格看)

 

系统的listview支持大容量显示也需要实现手动管理数据显示,貌似是 OnScrollUp  OnScrollDown等几个事件处理进行重绘要显示的那些行。

归真 | 园豆:605 (小虾三级) | 2012-07-14 19:57
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册