aardio传递到C#中DataTable显示大量数据的优化办法

By admin at 2022-04-19 • 1人收藏 • 876人看过

如题:

之前有写过几个调用dataGridView来显示数据表格的示例, 

测试发现如果直接for循环一句一句add会很慢. 代码如下:

//创建随机数据
dataTable.BeginLoadData();
for(i=1;50000;1){
    row = dataTable.NewRow();
    //第一种方式
    row.Item["RowIndex"] = i;
    row.Item["StringColumn"] = string.random(5);
    row.Item["DecimalColumn"] = 3.1415 / (i + 1);
    row.Item["BooleanColumn"] = (math.random(1,10)%2==0)?true:false;
    //第二种方式
    //row.ItemArray = {i, string.random(5),3.1415 / (i + 1) ,(math.random(1,10)%2==0)?true:false};
    dataTable.Rows.Add(row);
}
dataTable.EndLoadData();

可以测试发现, 如果数据非常大的时候显示就会非常慢 , 

我猜测可能是因为每次和c#传递和交换数据aardio都要封包解包导致. 

知道原因后, 就可以写个dll来直接传递aar中的table表到c#程序集中, 这样速度就可以达到和c#中使用一样的速度了.

代码如下:

import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=759;bottom=469)
winform.add(
custom={cls="custom";text="自定义控件";left=0;top=0;right=760;bottom=470;bgcolor=12639424;db=1;dl=1;dr=1;dt=1;z=1}
)
/*}}*/

import console
console.open()

import System.Windows.Forms;
var Forms = System.Windows.Forms;
var dataGridView = Forms.CreateEmbed("DataGridView",winform.custom); 
dataGridView.ColumnHeadersHeightSizeMode = 2; //避免在高分屏下错乱 
  
import System.Type;
import System.Data; 
 
var Data = System.Data;
var dt =Data.DataTable("DT"); 
//定义列格式
var integerColumn = Data.DataColumn("RowIndex",System.Type.GetType("System.Int32"));
var stringColumn = Data.DataColumn("StringColumn",System.Type.GetType("System.String"));
var decimalColumn = Data.DataColumn("DecimalColumn",System.Type.GetType("System.Decimal"));
var boolColumn = Data.DataColumn("BooleanColumn",System.Type.GetType("System.Boolean"));
//绑定格式
dt.Columns.Add(integerColumn);
dt.Columns.Add(stringColumn);
dt.Columns.Add(decimalColumn);
dt.Columns.Add(boolColumn);

//填充大量数据
var data={}
for(i=1;50000;1){
	data[i] = { i, "Txt"+i,math.random(), math.round(math.random()*10)%2?true:false };
}

//--------------------------------------------------------
//转换aardio的table表到c#的List表
var listdata = dotNet.createArrayList(data);

//引用数据传递dll
var convertdll = dotNet.load("\ListTodataTable.dll");
var Table = convertdll.import("ListTodataTable.Table");//Create
//写入list数据到DataTable
Table.WriteTo(dt,listdata);
//------------------------------------------------------

//显示数据
var dataView = System.Data.DataView(dt);
dataGridView.DataSource = dataView;
dataGridView.EditMode=2; 
  

winform.show();
win.loopMessage();

image.png

可以看到无论多大的数据量,上面速度都回来了.5W数据从创建界面到显示完成只需要2秒.

ListTodataTable.dll程序集和测试工程如下:

ListTodataTable.zip



下面将c#生成这个dll程序集的代码分享如下:

using System;
using System.Collections;
using System.Data;

namespace ListTodataTable
{
    public class Table
    {
        public static void WriteTo(DataTable dataTable , object args )
        {
            ArrayList list = (args as ArrayList);
            dataTable.BeginLoadData();
            for (int i = 0; i < list.Count; i++)
            {
                DataRow dataRow = dataTable.NewRow();
                var dlist = (list[i] as Array);
                for (int j = 0; j < dlist.Length; j++)
                {
                    dataRow[j] = dlist.GetValue(j);
                }
                dataTable.Rows.Add(dataRow);
            }
            dataTable.EndLoadData();
        }
    }
}


6 个回复 | 最后更新于 2022-05-18
2022-04-20   #1

正在为这个速度的事苦恼,刚好您来了...

我也想直接写dll,没付出行动...

谢谢

2022-05-10   #2

鉴于还有人问怎么内嵌dotnet程序集dllexe里 , 生成独立绿色的exe:

使用dotnet.reference()功能即可. 

比如: 针对我上面那个数据ListTodataTable.dll 示例, 你把用到的dll放到工程的res目录里然后调用即可,  完整的内嵌代码工程如下:

import win.ui;
/*DSG{{*/
mainForm = win.form(text="aardio工程4";right=868;bottom=522;bgcolor=15780518)
mainForm.add()
/*}}*/

import console
console.open()

import dotNet;
import System.Windows.Forms;
var Forms = System.Windows.Forms;
var dataGridView = Forms.CreateEmbed("DataGridView",mainForm); 
dataGridView.ColumnHeadersHeightSizeMode = 2; //避免在高分屏下错乱 
  
import System.Type;
import System.Data; 
 
var Data = System.Data;
var dt =Data.DataTable("DT"); 
//定义列格式
var integerColumn = Data.DataColumn("RowIndex",System.Type.GetType("System.Int32"));
var stringColumn = Data.DataColumn("StringColumn",System.Type.GetType("System.String"));
var decimalColumn = Data.DataColumn("DecimalColumn",System.Type.GetType("System.Decimal"));
var boolColumn = Data.DataColumn("BooleanColumn",System.Type.GetType("System.Boolean"));
//绑定格式
dt.Columns.Add(integerColumn);
dt.Columns.Add(stringColumn);
dt.Columns.Add(decimalColumn);
dt.Columns.Add(boolColumn);

//填充大量数据
var data={}
for(i=1;50000;1){
	data[i] = { i, "Txt"+i,math.random(), math.round(math.random()*10)%2?true:false };
}

//--------------------------------------------------------
//转换aardio的table表到c#的List表
var listdata = dotNet.createArrayList(data);

//引用数据传递dll
dotNet.reference({
    ["ListTodataTable.Table"] = "\res\ListTodataTable.dll";
})
var Table = dotNet.import("ListTodataTable.Table");//Create
//写入list数据到DataTable
Table.WriteTo(dt,listdata);
//------------------------------------------------------

//显示数据
var dataView = System.Data.DataView(dt);
dataGridView.DataSource = dataView;
dataGridView.EditMode=2; 
  


mainForm.show();
return win.loopMessage();


可以看到内嵌dotnet程序集dll的关键代码:

//引用数据传递dll
dotNet.reference({
    ["ListTodataTable.Table"] = "\res\ListTodataTable.dll";
})
var Table = dotNet.import("ListTodataTable.Table");//Create
//写入list数据到DataTable
Table.WriteTo(dt,listdata);

所以, 如果你调用了多个程序集dll , 都可以用上面的方式 ,reference()里是一个表, 你可以插入任意多个dll声明..

注意这个方式是专门针对 c#的程序集dll.

需要内嵌的文件放入到了res目录里同步目录后, 后面使用就不需要加$符号, 其他目录的话需要加$内嵌资源到工程里.



2022-05-17   #3

运行测试代码,不显示check列
image.png
是我哪里弄错了?

2022-05-17   #4

回复#3 @money :

如果打包的示例运行没问题,就是你代码有问题。aar范例里也有datalistview示例,也可以运行看看

2022-05-17   #5

我用示例没问题

2022-05-18   #6

找到原因了
dataGridView.AutoSizeRowsMode  = 11/*DisplayedCells*/ //修正部分高分屏下不显示复选框
谢谢各位

登录后方可回帖

登 录
信息栏
公 告:

专注分享

谢绝纯提问

谢谢合作!
本站域名:HtmLayout.Cn
aardio可以快速开发上位机,本站主要记录了学习过程中遇到的问题和解决办法及aardio代码分享

这里主要专注于aardio学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.

Aardio 官方站:Aardio官方
Aardio最新功能:Aardio官方更新日志
本 站 主 站:Stm32cube中文网
Sciter中文在线文档Sciter在线学习文档
空间赞助:才仁机械
打赏本站
Loading...