非常频繁地更新datagridview

我在C#中合理的时间刷新我的DataGridView时遇到了麻烦(我是新手,我已经习惯了java …)。

我通过网络获取数据,每秒发送20个包。 我想解析数据并将其放在DataGridView中。 我还想调整DataGridView更新的时间间隔,从0.1秒到1分钟。

所以我创建了一个额外的线程,它读取包并将它们解析为一个数组。 我也有一个Timer,我用它来改变Interval。 在每个计时器滴答声中,我将DataSource重新分配给DataGridView。

有趣的是,当我这样做时,即使我将计时器设置为0.1秒,它也只会被触发一次。 如果我不刷新DataGridView,它会被触发每秒10次,就像它应该的那样。

所以我假设我更新DataGridView的方法太耗时。 但是我需要做些什么来提高它的效率,所以我可以每秒更新10次而没有任何问题?

这是我使用的代码:

public MyForm() { InitializeComponent(); timer = new System.Windows.Forms.Timer(); timer.Interval = (1 * 1000); // 1 secs timer.Tick += new EventHandler(timer_Tick); timer.Start(); readNetworkValues = true; networkReader = new Thread(() => { Thread.CurrentThread.IsBackground = true; byte[] data = new byte[1024]; IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 49003); UdpClient newsock = new UdpClient(ipep); IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); while (readNetworkValues) { data = newsock.Receive(ref sender); dataSet = parseData(data); //Decrypts the data } newsock.Close(); }); networkReader.Start(); } private void timer_Tick(object sender, EventArgs e) { if (dataSet != null) { lock (dataSet) { int currentRow = dataGrid.FirstDisplayedScrollingRowIndex; dataGrid.DataSource = dataSet; dataGrid.FirstDisplayedScrollingRowIndex = currentRow; } } } 

您想要更新的单元格数量以及所需的更新速率足以导致闪烁滞后

要避免它,您可以为DataGridView打开DoubleBuffering

默认情况下不会公开此属性。 所以有一个选择

  • 创建一个子类
  • 通过反思访问它

这是一篇演示前者的post 。 它是针对滚动闪烁的情况编写的,但也有助于避免更新滞后。 该课程可能如下所示:

 public class DBDataGridView : DataGridView { public new bool DoubleBuffered { get { return base.DoubleBuffered; } set { base.DoubleBuffered = value; } } public DBDataGridView() { DoubleBuffered = true; } } 

您可以将此类添加到项目中,或者只是添加到表单类(在最后一个curl之前)。编译它将显示在ToolBox中。

另一种选择使用reflection ; 这是一个适用于任何类型控件的通用函数:

 using System.Reflection; static void SetDoubleBuffer(Control ctl, bool DoubleBuffered) { typeof(Control).InvokeMember("DoubleBuffered", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, ctl, new object[] { DoubleBuffered }); } 

两种方式都可以DoubleBuffering打开和关闭DoubleBuffering ; 前者通过现在暴露的属性 ,后者通过方法的bool param。