我在合理的时间内用C#刷新DataGridView时遇到麻烦(我是btw的新手,我习惯于Java …)。
我正在通过每秒20个数据包发送的网络获取数据。我想解析数据并将其放在DataGridView中。我还想将DataGridView的更新间隔从0.1秒调整为1分钟。
因此,我创建了一个额外的线程,该线程读取程序包并将其解析为数组。我还有一个计时器,可用于更改时间间隔。在每个计时器刻度上,我都将数据源重新分配给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; } } }
该 细胞的数量 要更新,并在 更新率 ,你要足够高,以引起 闪烁 和 滞后 。
为了避免它,你可以打开DoubleBuffering了DataGridView。
DoubleBuffering
DataGridView
默认情况下不公开此属性。所以可以选择
这是一个展示前者的帖子。它是为滚动闪烁而编写的,但也有助于避免更新滞后。该类可能看起来像这样:
public class DBDataGridView : DataGridView { public new bool DoubleBuffered { get { return base.DoubleBuffered; } set { base.DoubleBuffered = value; } } public DBDataGridView() { DoubleBuffered = true; } }
您可以将此类添加到项目中,也可以将其添加到表单类中(在最后一次卷曲之前)。进行编译,它将显示在工具箱中。
另一种选择是 反射 ; 这是一个通用函数,适用于任何类型的控件:
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方法的参数。
bool