winForm dataGridView性能问题 [英] winForm dataGridView performance issue

查看:133
本文介绍了winForm dataGridView性能问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,



这是我的情况,我有一个应用程序可以生成使用dataGridView显示财务数据的窗口。我的数据结构(bindingList)绑定到dataGridView。我的应用程序每分钟接收500到2000条消息。消息来自另一个线程所以我在正确的线程上调用我的控件(Control.BeginInvoke())我注意到当我打开多个窗口并且消息以2000 / min的速率进入时,只有有焦点的窗口正在更新!有人可以向我解释发生了什么,以及是否有解决方案吗?



 public delegate void UpdateDataTblDel(MyMsgType msgType ,MyData数据); 

公共类主要:表格
{
MyDataFeed dataFeed = new MyDataFeed();
DataTable dataTbl = new DataTable();

public Main()
{
Init();

CreateColumns();

dataFeed.Data + = new DataEvntHndlr(DataHandler);
}

private void CreateColumns()
{
DataColumn col;

col = new DataColumn(ID);
col.DataType = System.Interger;
dataTbl.Columns.Add(col);

col = new DataColumn(Price);
col.DataType = System.Double;
dataTable.Columns.Add(col);

DataColumn [] primaryKey = new DataColumn [1];
primaryKey [0] = dataTbl.Columns [ID];
dataTbl.PrimaryKey = primaryKey;
}

private void DataHandler(MyMsgType msgType,MyData data)
{
this.BeginInvoke(new UpdateDataTblDel(UpdateDataTbl),new object [] {m​​sgType,data });
}

private void UpdateDataTbl(MyMsgType msgType,MyData data)
{
DataRow row = null;

row = dataTbl.Rows.Find(data.ID);

if(row == null)
{
row = dataTbl.NewRow();
row [ID] = data.ID;
row [Price] = data.Price;

dataTbl.Add(row);
}
else
{
if(msgType == MyMsgType.Remove)
{
row.Delete();
}
else
{
row [Price] = data.Price;
}
}
}

private void button_Click(object sender,EventArgs e)
{
查看视图=新视图(dataTbl) ;
view.Show();
}
}

public Enum MyMsgType
{
删除,
添加,
更新
}

公共类MyData
{
公开双价;
public int ID;

public MyData(double price,int id)
{
Price = price;
ID = id;
}
}

公共类查看:表格
{
公共视图(DataTable dataTbl)
{
Init() ;

dataGridView.DataSource = dataTbl;
}
}





提前致谢,

-DA

解决方案

Alen,



好​​的,我明白了。看看你的数据交换有多密集,我严重怀疑整个架构是否合理。但是,由于我不知道所有这些活动的最终目的,我不能建议任何特别的改进它。



同时,我的想法是无限地填充 DataGridView 的实例,尤其是相对较高的速率对你来说不管怎么样,无论你付出多少努力来优化它。您是否认为迟早可能会发生所有可用内存不足以保存您的UI?



因此,可能有不同的方法;由于我上面解释的原因,我无法概述它们。因此,您应该接受的第一个原则是: UI用户永远不需要一次看到所有消息。一旦你理解了它,你就能以合理的方式设计你的UI。



所以,首先,你不应该更新你的 DataGridView ,即使您在收到数据时使用了一个。相反,你应该有一个小控件,每个消息来时都会更新。例如,如果只能显示三到四个数据元素,比如当前的消息数,那么两个时间点:对于第一个和最后一个接收到的消息;并且,也许还有你最近收到的消息的ID(姓名,描述,你的名字),只有一个。



首先,作为你的第一个行动在接收消息时,您应将所有收到的消息转储到磁盘上;你别无选择。数据应该在收到时表示,当用户决定查看时



用户应该能够选择什么要查看的消息范围。一种(不那么简单)方法将使用相同的非常 DataGridView 实例,但在虚拟模式下:

http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview。 virtualmode.aspx [ ^ ],

http:// msdn。 microsoft.com/en-us/library/2b177d6d.aspx [ ^ ]。



用户会得到一次可用的所有可用数据的印象,但是消息的范围应该是当用户滚动时,仅填充网格视图的可见部分。这是大量数据的常用解决方案。



-SA


我遇到的在我过去的应用程序中同样的东西,因为有自动更新功能。



您需要使用带有主键的DataTable而不是BindingList



使用带有PK的DataTable,您可以在DataTable上找到并更新受尊重的行,数据将在网格上自动刷新



请尝试以上或了解我如果您有任何疑问,我可以为您提供相同的示例代码。 :)

Hello everyone,

Here''s my situation, I have an application that spawns windows that display financial data with the dataGridView. My data structure (bindingList) is bound to the dataGridView. My apps is receiving anywhere from 500 to 2000 message per/min. The messages are coming from another thread so I have invoke my control on the correct thread (Control.BeginInvoke()) I notice when I have more than one window open and messages are coming in at a rate of 2000 per/min, only the window that has focus is updating! Can someone please explain to me what''s going on and if there is a solution to this?

public delegate void UpdateDataTblDel(MyMsgType msgType, MyData data);

public class Main: Form
{ 
   MyDataFeed dataFeed = new MyDataFeed();
   DataTable dataTbl = new DataTable();

   public Main()
   {
     Init();
     
     CreateColumns();

     dataFeed.Data += new DataEvntHndlr(DataHandler);
   }
   
   private void CreateColumns()
   {
      DataColumn col;

      col = new DataColumn("ID");
      col.DataType = System.Interger;
      dataTbl.Columns.Add(col);

      col = new DataColumn("Price");
      col.DataType = System.Double;
      dataTable.Columns.Add(col);
      
      DataColumn[] primaryKey = new DataColumn[1];
      primaryKey[0] = dataTbl.Columns["ID"];
      dataTbl.PrimaryKey = primaryKey;
   }

   private void DataHandler(MyMsgType msgType, MyData data)
   {
      this.BeginInvoke(new UpdateDataTblDel(UpdateDataTbl), new object[] {msgType, data});
   }

   private void UpdateDataTbl(MyMsgType msgType, MyData data)
   {
      DataRow row = null;
      
      row = dataTbl.Rows.Find(data.ID);
      
      if (row == null)
      {
          row = dataTbl.NewRow();
          row["ID"] = data.ID;
          row["Price"] = data.Price;
 
          dataTbl.Add(row);
      }
      else
      {
         if(msgType == MyMsgType.Remove)
         {
            row.Delete();
         }
         else
         {
            row["Price"] = data.Price;
         }
      }
   }

   private void button_Click(object sender, EventArgs e)
   {
      View view = new View(dataTbl);
      view.Show();
   }
}

public Enum MyMsgType
{
   Remove,
   Add,
   Update
}

public class MyData
{
   public double Price;
   public int    ID;

   public MyData(double price, int id)
   {
      Price = price;
      ID = id;
   }
}

public class View : Form
{
   public View(DataTable dataTbl)
   {
      Init();

      dataGridView.DataSource = dataTbl;
   }
}



Thanks in advance,
-DA

解决方案

Alen,

OK, I got it. Looking at how intensive your data exchange is, I seriously doubt that the whole architecture is reasonable. But, as I don''t know the ultimate purpose of all this activity, I cannot advise anything particular to improve it.

At the same time, the idea to infinitely populate an instance of a DataGridView, especially of relatively high rate won''t work for you anyway, no matter how much effort would you pay to "optimize" it. Did you think that sooner or later, it may happen that all of your available RAM will be not enough to hold your UI?

So, there can be different approaches; and I cannot overview them by the reason I explained above. So, the first principle you should embrace is: the UI user never needs to see all messages at once. Once you understand it, you will be able to design you UI in a reasonable way.

So, first of all, you should not update your DataGridView, even if you use one as data is received. Instead, you should have one small control which is update when each message comes. For example, if could show just three-four data elements, say, current number of messages, two points of time: for a very first and the last received messages; and, maybe also something like ID (name, description, you name it) of your most recently received message, only one.

First of all, as your first action on receiving messages, you should dump all received messages on disk; you just have no other choice. The data should be represented as it is received and as the user decides to look at it.

The user should be able to select what range of messages to look at. One (not so simple) approach would be using the same very DataGridView instance, but in virtual mode:
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.virtualmode.aspx[^],
http://msdn.microsoft.com/en-us/library/2b177d6d.aspx[^].

The user will have an impression of all the available data is available at once, but the range of messages should populate only the visible part of grid view as the user scrolls it. This is a very usual solution for big volumes of data.

—SA


I faced same-thing on my past application as there ware auto update functionality.

You need to use DataTable with Primary key instead of BindingList

Using DataTable with PK you can find and update respected row on DataTable and data will be refresh automatically on grid

Kindly try above or know me if you have any query so I can provide you sample code for same. :)


这篇关于winForm dataGridView性能问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆