望迷糊大虾再指点一下小弟,多谢了!(0分)

  • 主题发起人 主题发起人 delphi_xs
  • 开始时间 开始时间
D

delphi_xs

Unregistered / Unconfirmed
GUEST, unregistred user!
procedure Tm5_Thread.Execute;
var
i:integer;
begin
for i:=0 to 99do
begin

sleep(100);
Synchronize( CJ) ;
end;

end;
procedure Tm5_Thread.CJ;
begin
form1.listbox1.add('aaaaa');
end;

你可以把生成树结构的后台运算放在代替上面的sleep(100)
把更新树型控件的操作放在过程CJ中同步。
我造做以后,运行出错,
 
别点名呀,我是菜鸟一个,汗颜汗颜!
出什么错啊,是上面 的代码吗?我随手写来没有调试的
 
to 迷糊大虾
我才是真正的菜鸟呢!简单的问题都搞不定。庆幸有你热心的指点。
昨天有急事先走了,SORRY!
我把建树过程放在CJ过程里就不会出错,放到Tm5_Thread.Execute中就运行出错了。编译
可通过。
出错信息:
Project Project1:exe raised exception class eoleexception with message'尚未调用
coinitialize.'.Process stopped.Use step or run to contiue.
 
在Execute的开始加入下面这行
CoInitialize(nil);
在你的单元的Uses中加入:ActiveX
应该不会有问题了。
 
to feifeich大虾:
按照你说的做,没有出错信息。但是树也出不来。
 
下面是我实际编程中使用的线程处理,刚好也是添加树型节点,还有递归和WebService,基本没有修改:
--------------------------
// 获取用户组线程
TGetUserGroupsThead = class(TThread)
private
FOwnerHandle: HWND;
FUnitId: WideString;
FParentNode, tmpParentNode: TTreeNode;
FtvUnits: TTreeView;
FRecursive: Boolean;
FIsExpandAll: Boolean;
FRIO: TMyRIO;
// 私有变量
aUserGroup: TUserGroup;
p: ^TObject;
aNode: TTreeNode;
// 线程结束时通知父窗口
procedure FinalAct(Sender: TObject);
// 查询
procedure ListChildNode(parentId: String;
parentNode: TTreeNode);
// 同步添加节点
procedure AddNode;
protected
// 线程执行体
procedure Execute;
override;
public
// 构造函数
constructor Create(// 所有者窗口句柄
const OwnerHandle: HWND;
// 远程操作组件
RIO: TMyRIO;
// 单元ID
UnitId: WideString;
// 是否查询子单元
IsRecursive: Boolean;
// 父节点
ParentNode: TTreeNode;
// 节点
tvUnits: TTreeView;
// 是否全部展开
IsExpandAll: Boolean=true);
end;

{ TGetUserGroupsThead }
// 操作VCL组件,该方法必须同步调用
procedure TGetUserGroupsThead.AddNode;
begin
aNode := FtvUnits.Items.AddChildObject(tmpParentNode, aUserGroup.UnitName, p);
if FIsExpandAll then
tmpParentNode.Expand(True);
end;

constructor TGetUserGroupsThead.Create(const OwnerHandle: HWND;
RIO: TMyRIO;
UnitId: WideString;
IsRecursive: Boolean;
ParentNode: TTreeNode;
tvUnits: TTreeView;
IsExpandAll: Boolean);
begin
FOwnerHandle := OwnerHandle;
FRIO := RIO;
FUnitId := UnitId;
FRecursive := IsRecursive;
FParentNode := ParentNode;
FtvUnits := tvUnits;
FIsExpandAll := IsExpandAll;
OnTerminate := FinalAct;
FreeOnTerminate := True;
inherited Create(False);
end;

procedure TGetUserGroupsThead.Execute;
begin
CoInitialize(nil);
ListChildNode(FUnitId, FParentNode);
end;

procedure TGetUserGroupsThead.FinalAct(Sender: TObject);
begin
// 通知窗口线程已经结束
PostMessage(FOwnerHandle, WM_GetUnitsTheadDoneMsg, 0, 0);
end;

procedure TGetUserGroupsThead.ListChildNode(parentId: String;
parentNode: TTreeNode);
var
rs: ArrayOf_tns1_UserGroup;
i: Integer;
begin
// 下面是通过WebService取得用户组列表,你不用管
FRIO.Acquire;
try
rs := FRIO.ua.userGroupSearchUserGroups(FRIO.UserAuthConnection.LoginId,
FRIO.UserAuthConnection.LoginPwd, parentId, UA_FALSE);
finally
FRIO.Release;
end;
// 递归添加树型节点,因为只能每次取得当前节点的子节点所以使用了递归(服务器端接口的限制)
for i := Low(rs) to High(rs)do
begin
aUserGroup := TUserGroup.Create;
aUserGroup.aUserGroup := rs;
aUserGroup.UserAuthConnection := FRIO.UserAuthConnection;
new(p);
p^ := aUserGroup;
tmpParentNode := parentNode;
// 使用同步方法添加到form上的TreeView控件中
Synchronize(AddNode);
aUserGroup.Owner := aNode;
if FRecursive then
ListChildNode(aUserGroup.UserGroupId, aNode);
end;
end;
 
to feifeich:
非常感谢!!!我慢慢去消化。
只可惜没有分给你,很过意不去。总之多谢啦,
 
没关系啦,我来大富翁不是挣分的,赫赫,大家在这里应该互相帮助嘛,只是感觉这里的气氛有点不对,大家好像都是为了分。。。
 
建议你不要直接引用form1所在的单元,这么做还是会影响主界面,最好在要线程的构造函数中传入要同步的对象,这样再在synchronize的函数里通过对象指针操纵界面元素,效果会很理想。
个人的一点经验,仅供参考!
 
to feifeich 大虾:
看了你的代码,编程思想我懂,但一运用到我的程序中就不行了。我是根据表的记录建树
的。表有两个字段,一个字段值为01,0101,0102,02,0201,020101,……,另一个
为节点text.
我把建树过程分割开来,达到了多线程的效果,但是形成的树形结构不对,只能形成两级
节点,我觉得我的建树过程不好用多线程。
你能详细的指点我么?贴给我能运用多线程的建树代码,我表的结构不能改了。
刚开始做程序不久,给你添麻烦了。唉,发觉自己好笨……
 
to phuang 大虾:
多谢你的建议,我试试你的方法。
 
呵呵,这个贴子还没结呢。
你最好把你的关键代码贴出来,按你的表结构用递归可以生成树啊,这和用不用线程
没关系。
 
好的,下面是我的代码:
procedure TForm1.FormCreate(Sender: TObject);
begin
thread5:=Tm5_Thread.Create(false);
end;
--------------------------------------------------------------------------
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
jpeg, ExtCtrls,OleCtrls, ShockwaveFlashObjects_TLB, ComCtrls, Grids,
DBGrids, Db, ADODB,shellapi, StdCtrls, Buttons,ActiveX;//多了引用单元,没管它
type
Tm5_Thread = class(TThread)
private
{ Private declarations }
protected
procedure Execute;
override;
public
procedure cj;
end;

implementation
{ Important: Methods and properties of objects in VCL can only be used in a
method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure Tm5_Thread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
}
{ Tm5_Thread }
uses unit1;
//构造树形结构---------------------------------
procedure Tm5_Thread.Execute;
type
TAreaID = record
ID: String[20];
Len: Integer;
end;
PAreaID = ^TAreaID;
var tmpNode:TtreeNode;
AreaData:^TAreaID;
i,j:integer;
begin
//exit;
CoInitialize(nil);
ADOQuery_s:=TADOQuery.Create(self);
ADOQuery_s.Connection:=adoconn;
with ADOQuery_s do
begin
Close;
Sql.Clear ;
SQL.Add('SELECT aname,acode FROM m5_code where (LEN(Acode) = :AreaLen)');
SQL.Add('order by Acode');
Parameters.ParamByName('AreaLen').value := 2;
Open;
First;
end;

with ADOQuery_sdo
begin
while not(Eof)do
begin
tmpNode := Tree_m5.Items.Add(nil, FieldByName('Aname').AsString);
new(AreaData);
AreaData.ID := FieldByName('Acode').AsString;
AreaData.Len := 2;
tmpNode.Data := AreaData;
Next();
end;
Close();
for i := 2 to 5do
begin
Parameters.ParamByName('AreaLen').value:= i * 2;
Open();
while not(Eof)do
begin
tmpNode := nil;
for j := Tree_m5.Items.Count - 1do
wnto 0do
begin
AreaData := Tree_m5.Items[j].Data;
if Copy(FieldByName('Acode').AsString, 1, AreaData.Len) = AreaData.ID then
begin
tmpNode := Tree_m5.Items[j];
Break;
end;
end;
tmpNode := Tree_m5.Items.AddChild(tmpNode, FieldByName('Aname').AsString);
new(AreaData);
AreaData.ID := FieldByName('Acode').AsString;
AreaData.Len := i * 2;
tmpNode.Data := AreaData;
Next();
end;
Close();
end;
Freeandnil();
end;
end;
//构造树形结构---------------------------------
procedure Tm5_Thread.cj;
begin
//我知道不能把建树过程全部放在Execute中,但我把代码拆来拆去总拆不好,指针不能同步。
end;
麻烦你指点。

 
Tm5_Thread = class(TThread)
private
{ Private declarations }
procedure addtree(acode:string;Cnode:ttreenode);
protected
procedure Execute;
override;
end;
procedure Tm5_Thread.Execute;
type
TAreaID = record
ID: String[20];
Len: Integer;
end;
PAreaID = ^TAreaID;
var tmpNode:TtreeNode;
AreaData:^TAreaID;
i,j:integer;
begin
CoInitialize(nil);
addtree('',nil);
Freeandnil();
end;

procedure Tm5_Thread.addtree(acode:string;Cnode:ttreenode);
var
codelen:integer;
begin
len:=length(acode);
ADOQuery_s:=TADOQuery.Create(nil);
try
ADOQuery_s.Connection:=adoconn;
//adoconn最好通过参数传进来
with ADOQuery_s do
begin
Close;
Sql.Clear ;
SQL.Add('SELECT aname,acode FROM m5_code where LEN(Acode) ='+inttostr(codelen+2));
SQL.Add('and acode like '+quotedstr(acode+'%')+'order by Acode');
Open;
while not(Eof)do
begin
tmpNode := Tree_m5.Items.Addchild(cnode, FieldByName('Aname').AsString);
//上面一行单写成一个过程,需要同步 !!!
new(AreaData);
AreaData^.ID := FieldByName('Acode').AsString;
AreaData^.Len := length(AreaData.ID);
tmpNode.Data := AreaData;
addtree(FieldByName('Acode').AsString,tmpnode);
//递归调用
Next;
end;
end;
finally
ADOQuery_s.free;
end;
end;
我理解你构造树形的规则是:字节点acode长度=父节点acode长度+2,不只对不对?
同步我表示出来了但没做,你按楼上的方法处理就行。代码随手写的没调试,可能错误多多!:)
 
多谢迷糊大虾,我按你的方法做了,但是运行后老报错,算了,我笨得不行.
在网上看了一下,你对任何人都很热心,非常感谢你对我帮助,:)
 
不用客气,反正闲来无事。
上面的代码我没调试,肯定错误多多,不过你看大概意思就行了,你贴出的代码看,你建树的层次是固定的,我只是觉得用递归更好一些,而且你的表结构可以用递归
 
接受答案了.
 
后退
顶部