多线程加载数据后数据部分丢失,求助。(50)

  • 主题发起人 主题发起人 wind_2005
  • 开始时间 开始时间
W

wind_2005

Unregistered / Unconfirmed
GUEST, unregistred user!
我写了下面一个线程类,该线程从数据库中取出数据,最终将取出的数据加载到主线程的一个combobox控件中。加载到combobox控件的Objects列表中是一个个Panel组件,该panle组件上有多个子panel,每个子panel上都有若干image控件。 在主线程中,当选择combobox控件选项时,会将该combobox控件选项中包含的panel组件及包含的所有子组件显示到窗体界面上。 存在的问题是:组件显示到窗体上之后,组件内包含的个别image组件显示不正常。 如果不用多线程,直接在主线程中以相同的方式加载数据后,完全正常。 还望各们大侠帮帮忙,谢谢了! TLoadComponentThread = class(TThread) private ComponentList: TComboBox
InComponentList: TStringList
ADOQuery: TADOQuery
protected procedure Execute
override
destructor Destroy
override
procedure GetComponent
procedure SetToMainList
//将所获取到的对象列表加载至主线程的对象列表中 public constructor Create(aComponentList: TComboBox
aConnection: TADOConnection)
end
{ TLoadComponentThread } constructor TLoadComponentThread.Create(aComponentList: TComboBox
aConnection: TADOConnection)
begin InComponentList := TStringList.Create
ADOQuery := TADOQuery.Create(nil)
ADOQuery.Connection := aConnection
ComponentList := aComponentList
FreeOnTerminate := True
inherited Create(False)
end
destructor TLoadComponentThread.Destroy
var i: Integer
begin FreeAndNil(InComponentList)
FreeAndNil(ADOQuery)
inherited
end
procedure TLoadComponentThread.Execute
begin inherited
GetComponent
end
//在此过程中将数据库中取出的数据加载到InComponentList procedure TLoadComponentThread.GetComponent
var i: Integer
BlobStream: TADOBlobStream
aHouse: TComponentHouse
begin //获取数据 ADOQuery.SQL.Text := 'SELECT * FROM S_Component'
if ADOQuery.Active then ADOQuery.Close
ADOQuery.Open
//将数据库中取出的数据加载到InComponentList for i := 0 to ADOQuery.RecordCount - 1 do begin if Terminated then Exit
     //此处的'COMPONENT'字段保存了一个Panel组件,该Panel组件上有若干Panel或Image组件  BlobStream := TADOBlobStream.Create(TBlobField(ADOQuery.FieldByName('COMPONENT')), bmRead)
try aHouse := BlobStream.ReadComponent(aHouse) as TComponentHouse
aHouse.BindEven
InComponentList.AddObject(aHouse.ComponentHouseName, aHouse)
aHouse := nil
finally BlobStream.Free
end
ADOQuery.Next
end
Synchronize(SetToMainList)
end
//将InComponentList中的数据转移到主线程的ComponentList procedure TLoadComponentThread.SetToMainList
var i: Integer
begin for i := 0 to InComponentList.Count - 1 do begin if Terminated then Exit
ComponentList.Items.AddObject(InComponentList.Strings, (InComponentList.Objects as TComponentHouse))
FToMainIndex := i
end
end;
 
InComponentList.AddObject(aHouse.ComponentHouseName, aHouse)
是否 需要 Synchronize ?
 
hfghfghfg 谢谢你的回复:下面这样好像语法不对 Synchronize(InComponentList.AddObject(aHouse.ComponentHouseName, aHouse))
如果你是说用  Synchronize(GetComponent);的话,那么我用多线程就没意义了因为GetComponent中的处理可能很复杂,较慢,所以我想在GetComponent中处理完成后,再将结果传给主线程的combobox列表中,谢谢了!
 
函数GetComponent中对VCL控件InComponentList进行了操作,好像需要用Synchronize来调用GetComponent函数
 
 Synchronize(GetComponent);的话,那么我用多线程就没意义了因为GetComponent中的处理可能很复杂,较慢,所以我想在GetComponent中处理完成后,再将结果传给主线程的combobox列表中,有没有可能实现?谢谢各位了![:)]
 
关注下...我也想知道结果
 
问题有待解决,自己顶一下,谢谢各位了!
 
Image刷新问题,解决方法: ImageN.Graphics:=Nil
ImageN.Graphics:=在赋值
即可!呵呵!
 
谢谢wql,你提醒了我,应该是Image刷新问题,但是我在image中没有加载图片,只是在其canvas上画了几个图形,应该如何处理?非常感谢!
 
在重画前,我已经调用了 Canvas.FillRect(ClientRect);[:)]
 
问题解决,Canvas是非线程安全的,需要在操作Canvas时添加lock,unlock.
 
多人接受答案了。
 
那到底怎么个不正常法? 不明~, 个人觉得跟线程没关系.
 
后退
顶部