c# - 非常频繁地更新datagridview

标签 c# datagridview

我无法在合理的时间内使用 C# 刷新我的 DataGridView(顺便说一句,我是新手,我习惯了 java...)。

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

所以我创建了一个额外的线程,它读取包并将它们解析为一个数组。我还有一个定时器,我用它来改变间隔。在每个计时器滴答声中,我将 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

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

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

Here is a post这证明了前者。它是为滚动闪烁的情况而编写的,但也有助于避免更新滞后。该类可能看起来像这样:

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

    public DBDataGridView()
    {
        DoubleBuffered = true;
    }
}

您可以将此类添加到项目或简单地添加到表单类(在最后一个 curl 之前。)编译,它将显示在工具箱中。

另一个选项使用反射;这是一个通用函数,适用于任何类型的控件:

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;前者通过现在公开的 property,后者通过方法的 bool 参数。

关于c# - 非常频繁地更新datagridview,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44185298/

相关文章:

c# - 如何获得 ListBox 的子控件?

c# - Linq to Xml 到 Datagridview

c# - 如何将 DataGridView 内容转换为自定义对象的 List<>?

.net - 在 DataGridViewColumn 中混合单元格类型

c# - 从 DataGridView 中删除列

c# - 日期时间转换和解析 DateTime.Now.ToString ("MM/dd/yyyy hh:mm:ss.fff")

c# - 通过在 Web 应用程序表单中返回一串数据来测试 Web 服务

c# - 将 DataRow 集合与 List<T> 进行比较

vb.net - 如何: Change datagridview LinkColumn Text when clicked

c# - 我的 Xpath 有什么问题吗?