通过线程读取数据到DBGrid时不正常显示!!!!!!!!!

abcdwell 2011-05-30 03:05:23
由于数据比较多,
如果不用线程来读取则会出现界面长时间假死的状态,非常不爽,

用线程后会出现一些奇怪的现象:
调用线程后,DBGrid会闪一下,然后要拖动滚动条才可以看到显示不正常的数据;
具体表现为: 列宽不对/很多区域为空白,好像没有数据一样,



// 线程类的定义与实现:
type
TLoadDataThrd = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
procedure SetGridWidth;
public
adoConn : TADOConnection;
SQLString:WideString;
DBGridTemp:TDBGrid;
adsData:TADODataSet;
dsData:TDataSource;
end;

{ TLoadDataThrd }
procedure TLoadDataThrd.SetGridWidth;
var
i : integer;
begin
for i := 0 to DBGridTemp.Columns.Count-1 do
begin
DBGridTemp.Columns[i].Width := 70;
end;
end;

procedure TLoadDataThrd.Execute;
begin
adsData.Close;
adsData.Connection := adoConn;
adsData.CommandText := SQLString;
try
adsData.Open;
if adsData.Active then
begin
SetGridWidth;// 虽然此处调用了此函数来设置Grid列宽度,但是最后显示出的宽度根本不正确!
end;
finally
end;
end;




// 在窗口类中实现调用线程
{TfrmData}
//function TfrmData.getSQLCmd:WideString; // 获取 sql语句的函数,返回如:select * from .....
// adoConn1:TAdoConnection;
// DBGridTest:TDBGrid;
// adsTest:TADODataSet;
// dsTest:TDatasource;
function TfrmData.RunThread(adoConnTemp:TADOConnection; SQLString : widestring;
DBGridTemp:TDBGrid; adsTemp: TADODataSet; dsTemp : TDataSource): TLoadDataThrd;
var
loadThread:TLoadDataThrd;
begin
loadThread := TLoadDataThrd.Create(True);
loadThread.adoConn := adoConnTemp;
loadThread.DBGPM := DBGridTemp;
loadThread.adsData := adsTemp;
loadThread.dsData := dsTemp;
loadThread.SQLString := SQLString;
loadThread.Resume;

Result := loadThread;
end;

// 此处调用线程取数据库数据
procedure TfrmData.btnSearchClick(Sender: TObject);
begin
RunThread(adoConn1,getSQLCmd,DBGridTest,adsTest,dsTest);
end;

...全文
240 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
abcdwell 2011-06-13
  • 打赏
  • 举报
回复
谢谢楼上
lindaozhi 2011-06-13
  • 打赏
  • 举报
回复
顶起~~~~
abcdwell 2011-06-03
  • 打赏
  • 举报
回复
彻底黄了?
abcdwell 2011-06-02
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 dropme 的回复:]
貌似是线程退出不正确,一般是访问null值造成,慢慢调试呗~
[/Quote]
仔细检查也没发现访问null值的情况啊,

网上有没有类似的例子可以推荐的?
abcdwell 2011-06-01
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 yqdragon 的回复:]
Synchronize中的过程不能有参数
你可以把参数放在线程的局部变量里
然后在Synchronize调用的过程里访问它们
[/Quote]
之前没看清楚,这倒是个好办法!谢谢
haochin 2011-05-31
  • 打赏
  • 举报
回复
线程读取前,将dbgrid 和数据集断开。。

读完了,再连上。
dropme 2011-05-31
  • 打赏
  • 举报
回复

TMyThread=class(TThread)
private
FVar: Integer;
procedure UpdateUI;
...


procedure Execute; override;
begin
FVar:= 100;
..
Synchronize(UpdateUI);
end;

procedure UpdateUI;
begin
Form1.caption:= Inttostr(FVar);
end;



类似这种吧,线程单元里引入主窗体单元,把FrmMain传进来,在UpdateUI里更新主窗体;

其实没必要一定要用Synchronize,给主线程发消息,消息里面带参数,主线程收到消息处理参数也是可以的; 建议Google下 delphi+线程+UI,研究下看看~
abcdwell 2011-05-31
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 yqdragon 的回复:]
Synchronize中的过程不能有参数
你可以把参数放在线程的局部变量里
然后在Synchronize调用的过程里访问它们
[/Quote]
有没有类似的例子可以参考?
dropme 2011-05-31
  • 打赏
  • 举报
回复
貌似是线程退出不正确,一般是访问null值造成,慢慢调试呗~
abcdwell 2011-05-31
  • 打赏
  • 举报
回复
用了Synchronize,之前的现象是没有了,

不过,当窗口关闭时会出现一些莫名的错误,
如:invalid pointer operation,
Access violation at address ......
一竹 2011-05-30
  • 打赏
  • 举报
回复
学习了
yqdragon 2011-05-30
  • 打赏
  • 举报
回复
Synchronize中的过程不能有参数
你可以把参数放在线程的局部变量里
然后在Synchronize调用的过程里访问它们
abcdwell 2011-05-30
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 bdmh 的回复:]
你的function怎么定义的,不是随便一个就可以
[/Quote]
函数定义如下:
function SetGridWidth:Boolean;


还有一个问题就是,假如我的function/procedure带有参数,该如何用Synchronize来调用?
比如:
function SetGridWidth(iCount:integer):boolean;
abcdwell 2011-05-30
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 cgfhz 的回复:]
可视化控件不要在线程类里操作,可以用回调函数比较方便
[/Quote]
谢谢提醒,既然说了就请稍微具体点吧,谢谢啦
dropme 2011-05-30
  • 打赏
  • 举报
回复
Synchronize只能接收Procedure吧,而且Procedure不能带参数;需要传递数据的话可以向主线程发送个消息,主线程收到消息后处理~
国风 2011-05-30
  • 打赏
  • 举报
回复
可视化控件不要在线程类里操作,可以用回调函数比较方便
Oraclers 2011-05-30
  • 打赏
  • 举报
回复
试一下这个:
procedure TLoadDataThrd.Execute;
begin
adsData.Close;
adsData.Connection := adoConn;
adsData.CommandText := SQLString;
try
adsData.Open;
if adsData.Active then
begin
Synchronize(SetGridWidth);// 虽然此处调用了此函数来设置Grid列宽度,但是最后显示出的宽度根本不正确!
end;
finally
end;
end;
专制的网站 2011-05-30
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 bdmh 的回复:]
你的function怎么定义的,不是随便一个就可以
[/Quote]
一直以为 只能 ,procedure呢 ... 坐等讲解~~~
yqdragon 2011-05-30
  • 打赏
  • 举报
回复
意义不大,涉及到VCL都要进行同步操作
如果同步的时间很长则没有多大改变
建议数据如果很多的话进行分页显示
bdmh 2011-05-30
  • 打赏
  • 举报
回复
你的function怎么定义的,不是随便一个就可以
加载更多回复(2)
代码转载自:https://pan.quark.cn/s/a4b39357ea24 LA 1010 逻辑分析仪被视作一种效能卓越的数字信号分析设备,其核心功能在于对数字通信协议,例如I²C,进行检测与解构。本资源将集中阐述LA 1010的操作流程以及如何借助该设备对I²C协议的波形展开分析。 确保逻辑分析仪被正确地连接至目标系统是极为关键的环节。在运用LA 1010的过程中,必须将分析仪的通道0与通道1分别对应连接至目标装置的SCL(钟)与SDA(数据)线路。务必保证连接的稳固性且无任何干扰因素,以此确保数据采集的精确度。 随后,需要设定采样参数。采样频率对于能否成功捕捉到信号具有决定性的作用。针对I²C协议,通常选用的采样频率范围介于100kHz到400kHz之间,这一范围的选择取决于实际应用场景中I²C总线的运行速度。然而,LA 1010所能达到的最高采样速率可能高达500MHz,因此需要根据具体需求进行相应的调整。此外,还必须精心挑选适配目标设备工作电压的电压等级,例如3.3V、5V或1.8V。 在软件操作层面,需要选取恰当的通道与协议种类,即I²C。一旦启动采样,逻辑分析仪便开始记录相关数据。软件界面通常会实展示波形图,为观察与分析提供便利。 关于I²C协议波形的解读,我们可以遵循以下步骤: 1. 总线处于空闲状态:SCL与SDA均维持在高电平位置,这表明总线当前未进行数据传输。 2. 传输起始信号:当SCL处于高电平期间,SDA线从高电平转换至低电平,此动作标志着数据传输的开始。 3. 地址、数据及应答的识别:在每一个SCL高电平脉冲的持续间内,SDA线上的电平状态代表了数据位。地址与数据的传输均为双向过程,而读写标识则由SDA线上的电平来...
内容概要:本文介绍了一种基于有限元分析(FEA)获取的磁通链接图来构建高精度永磁同步电机(PMSM)数学模型的方法,并在Simulink环境中实现仿真。该方法通过有限元软件提取电机在不同工况下的非线性磁通特性数据,建立精确的磁链-电流-转子位置映射关系,有效克服了传统线性模型在反映铁芯饱和、交叉耦合等非线性效应方面的局限性。所构建的模型能够更真实地模拟PMSM的实际电磁行为,适用于高性能控制算法(如矢量控制、直接转矩控制、模型预测控制等)的研发与验证,显著提升了控制系统在动态响应、效率优化和稳定性方面的仿真准确性。; 适合人群:具备电机控制理论基础、熟悉有限元分析与Simulink仿真的研究生、科研人员及从事电机设计与驱动系统开发的工程技术人员。; 使用场景及目标:①用于高精度永磁同步电机控制系统的设计、仿真与性能评估;②支持先进控制策略(如MPC、滑模控制、自适应控制)在非线性电机模型上的验证与优化;③为电机参数敏感性分析、能效优化、故障诊断与容错控制研究提供可靠的仿真平台; 阅读建议:建议读者结合ANSYS Maxwell、JMAG等有限元工具与Matlab/Simulink进行联合仿真,掌握从电磁场建模、数据提取、查表插值到控制系统集成的完整流程,并参考文中模型架构与数据处理方法,逐步复现、验证并拓展适用于特定电机结构的高保真仿真模型。

2,508

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 数据库相关
社区管理员
  • 数据库相关社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧