首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

关于TreeView和线程结合出现的有关问题

2012-03-04 
关于TreeView和线程结合出现的问题刚开始学习线程和TreeView。。尝试着做了以下测试,但是出现了我无法解决的

关于TreeView和线程结合出现的问题
刚开始学习线程和TreeView。。尝试着做了以下测试,但是出现了我无法解决的问题,故请教之。
我尝试在模块左边用一个DBGridEh存放用户名列表,右侧用两个TreeView分别显示已拥有权限,全部权限,其中全部权限TreeView上能用红色标记已拥有权限。在选择到不同用户时刷新两个TreeView。而两个TreeView的生成我分别放在两个Thread中执行。
问题:在我快速滚动用户列表时导致Thread多次触发执行。弹出了错误提示:unable   to   insert   an   item
或者没有提示错误却出现TreeView显示的结果比预期结果要多了一些节点,估计是已经在产生TreeView时再度执行Thread导致的。
而如果我等待Thread完全执行完毕然后选择其他用户则不出现错误。
请问该如何解决?
***********************代码部分************************************
Thread1:
procedure   right1.Execute;
var   s:   string;   p:   ^string;
mt,   t,   ct:   TTreeNode;
ADO0,   ADO1,   ADO2,   ADO3,   ADO4,   ADO5:   TADOQuery;
begin
FreeOnTerminate   :=   True;
//创建所需ADOQ控件
ADO0   :=   TADOQuery.Create(nil);
ADO0.Connection   :=   Fmdm.ADOConnection1;
ADO1   :=   TADOQuery.Create(nil);
ADO1.Connection   :=   Fmdm.ADOConnection1;
ADO2   :=   TADOQuery.Create(nil);
ADO2.Connection   :=   Fmdm.ADOConnection1;
ADO3   :=   TADOQuery.Create(nil);
ADO3.Connection   :=   Fmdm.ADOConnection1;
ADO4   :=   TADOQuery.Create(nil);
ADO4.Connection   :=   Fmdm.ADOConnection1;

ADO3.Close;
ADO3.SQL.Clear;
s   :=   'select   m_code   from   ts_group_right   where   kind= ' '1 ' '   and   group_code= ' ' '   +   group_code   +   ' ' ' ';
ADO3.SQL.Add(s);
ADO3.Open;

ADO4.Close;
ADO4.SQL.Clear;
s   :=   'select   right_code   from   ts_group_right   where   kind= ' '2 ' '   and   group_code= ' ' '   +   group_code   +   ' ' ' ';
ADO4.SQL.Add(s);
ADO4.Open;                   //   取得已拥有权限

Fmrightset.TreeView1.Items.Clear;   //删除树
Fmrightset.TreeView1.Items.BeginUpdate;   //加快树创建速度

ADO0.Close;
ADO0.SQL.Clear;
s   :=   'select   menu_name,menu_code,state   from   ts_right_m   order   by   menu_code   desc ';
ADO0.SQL.Add(s);
ADO0.Open;
ADO0.First;
while   not   ADO0.Eof   do
begin
mt   :=   Fmrightset.TreeView1.Items.AddFirst(nil,ADO0.Fields[0].AsString);
New(p);           //分配内存
p^   :=   ADO0.Fields[1].AsString;   //内存赋值
mt.Data   :=   p;                       //写入data
    ADO1.Close;
    ADO1.SQL.Clear;
    s   :=   'select   m_name,m_code,state   from   ts_right_z   where   menu_code= ' ' '   +   ADO0.Fields[1].AsString   +   ' ' '   order   by   m_code ';
    ADO1.SQL.Add(s);
    ADO1.Open;       //对该节点查询子节点
    ADO1.First;
    while   not   ADO1.Eof   do
    begin
    t   :=   Fmrightset.TreeView1.Items.AddChild(mt,ADO1.Fields[0].AsString);
    if   ADO3.Locate( 'm_code ',ADO1.Fields[1].AsString,[])   =   True   then
    t.StateIndex   :=   1;
    //将编号转化为指针存入该节点data中
    New(p);
    p^   :=   ADO1.Fields[1].AsString;
    t.Data   :=   p;


        ADO2.Close;
        ADO2.SQL.Clear;
        s   :=   'select   right_name,right_code,state   from   ts_right_sub   where   m_code= ' ' '   +   ADO1.Fields[1].AsString   +   ' ' '   order   by   right_code ';
        ADO2.SQL.Add(s);
        ADO2.Open;               //对该节点查询子节点
        ADO2.First;
        while   not   ADO2.Eof   do
        begin
        ct   :=   Fmrightset.TreeView1.Items.AddChild(t,ADO2.Fields[0].AsString);
        //将编号转化为指针存入该节点data中
        New(p);
        p^   :=   ADO2.Fields[1].AsString;
        ct.Data   :=   p;
        if   ADO4.Locate( 'right_code ',ADO2.Fields[1].AsString,[])   =   True   then
        ct.StateIndex   :=   1;
        ADO2.Next;
        end;
    ADO1.Next;
end;
ADO0.Next;
end;

Fmrightset.TreeView1.Items.EndUpdate;//加快树创建速度

end;
////////////////////////////////////////
Thread2:
procedure   right2.Execute;
var   s:   string;   p:   ^string;
mt,   t,   ct:   TTreeNode;
ADO0,   ADO1,   ADO2,   ADO3,   ADO4,   ADO5:   TADOQuery;
begin
FreeOnTerminate   :=   True;
//创建所需ADOQ控件
ADO0   :=   TADOQuery.Create(nil);
ADO0.Connection   :=   Fmdm.ADOConnection1;
ADO1   :=   TADOQuery.Create(nil);
ADO1.Connection   :=   Fmdm.ADOConnection1;
ADO2   :=   TADOQuery.Create(nil);
ADO2.Connection   :=   Fmdm.ADOConnection1;

Fmrightset.TreeView2.Items.Clear;     //删除树
Fmrightset.TreeView2.Items.BeginUpdate;   //加快树创建速度

ADO0.Close;
ADO0.SQL.Clear;
s   :=   'select   menu_name,menu_code   from   ts_right_m   order   by   menu_code   desc ';
ADO0.SQL.Add(s);
ADO0.Open;                       //查询跟节点项目
ADO0.First;
while   not   ADO0.Eof   do
begin
mt   :=   Fmrightset.TreeView2.Items.AddFirst(nil,ADO0.Fields[0].AsString);
New(p);
p^   :=   ADO0.Fields[1].AsString;
mt.Data   :=   p;
    ADO1.Close;
    ADO1.SQL.Clear;
    s   :=   'select   m_name,m_code   from   ts_group_right   where   kind= ' '1 ' '   and   menu_code= ' ' '   +   ADO0.Fields[1].AsString   +   ' ' '   and   group_code= ' ' '   +   group_code   +   ' ' '   order   by   m_code ';
    ADO1.SQL.Add(s);
    ADO1.Open;
    ADO1.First;
    while   not   ADO1.Eof   do
    begin
    t   :=   Fmrightset.TreeView2.Items.AddChild(mt,ADO1.Fields[0].AsString);
    New(p);
    p^   :=   ADO1.Fields[1].AsString;
    t.Data   :=   p;
        ADO2.Close;


        ADO2.SQL.Clear;
        s   :=   'select   right_name,right_code   from   ts_group_right   where   kind= ' '2 ' '   and   m_code= ' ' '   +   ADO1.Fields[1].AsString   +   ' ' '   and   group_code= ' ' '   +   group_code   +   ' ' '   order   by   right_code ';
        ADO2.SQL.Add(s);
        ADO2.Open;               //对该跟节点查询子节点
        ADO2.First;
        while   not   ADO2.Eof   do
        begin
        ct   :=   Fmrightset.TreeView2.Items.AddChild(t,ADO2.Fields[0].AsString);
        New(p);
        p^   :=   ADO2.Fields[1].AsString;
        ct.Data   :=   p;
        ADO2.Next;
        end;
    ADO1.Next;
end;
ADO0.Next;
end;
Fmrightset.TreeView2.Items.EndUpdate;//加快树创建速度

end;
///////////////////////////////////////
from_main点击用户时:
procedure   TFmrightset.RunThread(Agroup_code:   string);
var   r1:   right1;   r2:   right2;
begin
//线程right1。right2分别刷新已有权限,全部权限
r2   :=   right2.Create(true);
r2.group_code   :=   Agroup_code;   //传递给线程参数
r2.Resume;
r1   :=   right1.Create(true);
r1.group_code   :=   Agroup_code;   //传递给线程参数
r1.Resume;
end;
///////////////////////////////////

[解决办法]
1、可能要在运行线程时对线程进行加锁控制;
2、对VCL组件的调用,要使用同时过程。

线程的使用有点复杂,我也不太行,哈哈
[解决办法]
把r1和r2的声明放到外面去
procedure TFmrightset.RunThread(Agroup_code: string);
begin
// 终止上一个查询过程
r1.Terminate;
r2.Terminate;
//线程right1。right2分别刷新已有权限,全部权限
r2 := right2.Create(true);
r2.group_code := Agroup_code; //传递给线程参数
r2.Resume;
r1 := right2.Create(true);
r1.group_code := Agroup_code; //传递给线程参数
r1.Resume;
end;

[解决办法]
对于这种作业,建议的处理方式是:
1.这个切换用户,需要一个时间间隔,以避开,用户快速滚动过程当中的更新,从而通过减少不必要的刷新而提高性能;
2.数据的采信整理放到线程当中;
3.将数据投放到VCL控件当中显示请使用同步执行。
[解决办法]
采用同步...

热点排行