Обновлять datagridview очень часто

У меня проблемы с обновлением моего DataGridView в разумные сроки в C# (что я новичок, кстати, я привык к 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;
            }
        }
    }

1 ответ

Решение

Количество ячеек, которые вы хотите обновить, а также частота обновления, которую вы хотите, достаточно высоки, чтобы вызвать мерцание и отставание.

Чтобы избежать этого вы можете включить DoubleBuffering для DataGridView,

Это свойство не доступно по умолчанию. Так что есть выбор

  • создание подкласса или
  • доступ к нему через отражение

Вот пост, который демонстрирует первое. Он был написан для случая мерцания прокрутки, но также поможет избежать задержек при обновлении. Класс может выглядеть так:

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

    public DBDataGridView()
    {
        DoubleBuffered = true;
    }
}

Вы можете добавить этот класс в проект или просто в класс формы (до самого последнего вьющегося). Скомпилируйте, и он появится в ToolBox.

Другой вариант использует отражение; Вот функция общего назначения, которая должна работать для любого типа управления:

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 включать и выключать по желанию; первый через теперь выставленную собственность, последний bool параметр метода.

Другие вопросы по тегам