通过线程读取数据到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;

...全文
206 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)

2,497

社区成员

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

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