我在合理的时间内用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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
该细胞的数量要更新,并在更新率,你要足够高,以引起闪烁和滞后。
为了避免它,你可以打开DoubleBuffering了DataGridView。
默认情况下不公开此属性。所以可以选择
这是一个展示前者的帖子。它是为滚动闪烁而编写的,但也有助于避免更新滞后。该类可能看起来像这样:
public class DBDataGridView : DataGridView
{
public new bool DoubleBuffered
{
get { return base.DoubleBuffered; }
set { base.DoubleBuffered = value; }
}
public DBDataGridView()
{
DoubleBuffered = true;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将此类添加到项目中,也可以将其添加到表单类中(在最后一次卷曲之前)。进行编译,它将显示在工具箱中。
另一种选择是反射 ; 这是一个通用函数,适用于任何类型的控件:
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 });
}
Run Code Online (Sandbox Code Playgroud)
两种方式都可以让您随意打开DoubleBuffering和关闭。前者通过现在暴露的属性,后者通过bool方法的参数。