关于线程的简单问题:线程与界面 ( 积分: 30 )

  • 主题发起人 主题发起人 ppqingyu
  • 开始时间 开始时间
P

ppqingyu

Unregistered / Unconfirmed
GUEST, unregistred user!
我对线程的理解不深,只知道如果用线程的话,那么在线程运行的同时,界面有可以进行其他的操作(不知道这样理解是否错了),但是做的线程好像不能达到目的.
我的线程是用于数据库查询操作,当查询完毕,用Synchronize同步把结果显示于表格之上.一次大概有八个或者十个线程运行,在线程运行期间,我的鼠标频频变成漏斗型,不能进行别的操作?怎么办?但是如果不进行同步显示结果就没有问题,怎么回事?
 
我对线程的理解不深,只知道如果用线程的话,那么在线程运行的同时,界面有可以进行其他的操作(不知道这样理解是否错了),但是做的线程好像不能达到目的.
我的线程是用于数据库查询操作,当查询完毕,用Synchronize同步把结果显示于表格之上.一次大概有八个或者十个线程运行,在线程运行期间,我的鼠标频频变成漏斗型,不能进行别的操作?怎么办?但是如果不进行同步显示结果就没有问题,怎么回事?
 
在线程运行的同时,界面可以进行其他的操作
 
Synchronize做一些控制工作,使你的线程临时成为应用程序主线程的一部分。在这个进程中,你可以访问VCL。
所以Synchronize是在主线程中执行 ,因为在主线程中执行,主线程在忙,所以这时你的界面不能进行其他操作
 
这么说是在同步时把显示结果的操作在主线程上运行所造成的,是不是这样?有没有其他的办法可以解决的?
 
这样:
Table.First;
while not Table.Eofdo
begin
Synchronize(AddRowToMainForm);
// 添加一条记录到主界面
Table.Next;
end;
而不要一次同步将所有记录添加到主界面上的。
 
一次一条会不会慢了?如果记录很多怎么办?
这是我线程的代码,给我看看.
unit UThread;
interface
uses
Classes,ADODB,DB,ActiveX,Dialogs,UFive;
type
FiveQuery = class(TThread)
private
{ Private declarations }
CreateConnection:TADOConnection;
CreateQuery:TADOQuery;
UseInQuery:TADOQuery;
UseInOutNum:Integer;
UseInBMPIndex:Integer;
// Conn1,Conn2:String;
UseSQL:String;
procedure SynchronizeSource;
protected
procedure Execute;
override;
public
constructor Create(Suspendec:Boolean;SQL:String;InConnection:TADOConnection;InQuery:TADOQuery;InOutNum:Integer;InBMPIndex:Integer);
destructor Destroy;override;
end;

implementation
procedure FiveQuery.SynchronizeSource;
var
i:integer;
begin
UseInQuery.Clone(CreateQuery);
Case UseInBMPIndex of
1:
begin
frmFive.cxFiveCompartTb.begin
Update;
for i:=1 to 9do
begin
if i<=UseInOutNum then
begin
frmFive.cxFiveCompartTb.Bands.Visible:=True;
frmFive.cxFiveCompartTb.Columns[i+1].Visible:=True;
end
else
begin
frmFive.cxFiveComparttb.Bands.Visible:=False;
frmFive.cxFiveCompartTb.Columns[i+1].Visible:=False;
end;
end;
frmFive.cxFiveCompartTb.EndUpdate;
frmFive.TabFiveCompartTb.ImageIndex:=0;
end;
2:
begin
frmFive.cxFiveCompartGroupTb.begin
Update;
for i:=2 to 10do
begin
if i<=UseInOutNum+1 then
frmFive.cxFiveCompartGroupTb.Columns.Visible:=true
else
frmFive.cxFiveCompartGroupTb.Columns.Visible:=False;
end;
frmFive.cxFiveCompartGroupTb.EndUpdate;
frmFive.TabFiveCompartGroupTb.ImageIndex:=0;
end;
3:
begin
for i:=1 to 9do
if i<=UseInOutNum then
frmFive.cxFiveHowCompartTb.Columns[i+1].Visible:=True
else
frmFive.cxFiveHowCompartTb.Columns[i+1].Visible:=False;
frmFive.TabFiveHowCompartTb.ImageIndex:=0;
end;
4:
begin
frmFive.TabFiveHowCountTb.ImageIndex:=0;
end;
5:
begin
//
end;
6:
begin
frmFive.cxFiveCountTb.begin
Update;
for i:=1 to 9do
begin
if i<=UseInOutNum then
begin
frmFive.cxFiveCountTb.Bands.Visible:=True;
frmFive.FiveCountChart.Series.ShowInLegend:=True;
end
else
begin
frmFive.cxFiveCountTb.Bands.Visible:=False;
frmFive.FiveCountChart.Series.ShowInLegend:=False;
end;
end;
frmFive.cxFiveCountTb.EndUpdate;
frmFive.TabFiveCountChart.ImageIndex:=0;
end;
7:
begin
frmFive.cxFiveGroupTbl.begin
Update;
for i:=1 to 9do
begin
if i<=UseInOUtNum then
frmFive.cxFiveGroupTbl.Bands.Visible:=True
else
frmFive.cxFiveGroupTbl.Bands.Visible:=False;
end;
frmFive.cxFiveGroupTbl.EndUpdate;
frmFive.TabFiveCountTb.ImageIndex:=0;
end;
8:
begin
for i:=1 to 9do
begin
if i<=UseInOutNum then
frmFive.FiveChart.Series.ShowInLegend:=True
else
frmFive.FiveChart.Series.ShowInLegend:=False;
end;
frmFive.TabFiveChart.ImageIndex:=0;
end;
9:
begin
frmFive.TabFiveHowChart.ImageIndex:=0;
end;
10:
begin
for i:=0 to 8do
begin
if i<=UseInOutNum-1 then
frmFive.FiveCountScaleChart.Series.ShowInLegend:=True
else
frmFive.FiveCountScaleChart.Series.ShowInLegend:=False;
end;
frmFive.TabFiveCountScaleChart.ImageIndex:=0;
end;
end;
// ReQuer.Clone(Quer);
end;
constructor FiveQuery.Create(Suspendec:Boolean;SQL:String;InConnection:TADOConnection;InQuery:TADOQuery;InOutNum:Integer;InBMPIndex:Integer);
begin
CoInitialize(nil);
Inherited create(Suspended);
FreeOnTerminate:=true;
UseInBMPIndex:=InBMPIndex;
try
// Conn:=TADOConnection.Create(nil);
CreateQuery:=TADOQuery.Create(nil);
UseInQuery:=InQuery;
CreateQuery.Connection:=InConnection;
UseInOutNum:=InOutNum;
UseSQL:=SQL;
except
ShowMessage('数据连接出错');
end;
end;

destructor FiveQuery.Destroy;
begin

// Conn.Free;
CreateQuery.Free;
CoUnInitialize;
inherited Destroy;
end;

procedure FiveQuery.Execute;
var
i:integer;
begin
try
CreateQuery.Close;
CreateQuery.SQL.Clear;
CreateQuery.SQL.Text:=UseSQL;
CreateQuery.Open;
Synchronize(SynchronizeSource);
except
ShowMessage('数据库连接错误');
end;

{ Place thread code here }
end;

end.
 
在SynchronizeSource中的第一行加application.processMessages;试试
 
把 Synchronize 去掉
 
不要用同步线程
采用互斥、信号量 线程
 
一次一条慢,那就一次10条、50条、或者100条呗,而把所有的记录一次同步添加显示肯定是不合适的。另外,由于是线程循环同步追加显示,慢点你在视觉上也未必感觉得到。
 
呵呵...越来越有趣了.
to 子瑜:加application.processMessages;已经被否定,情况依然;
to okgxsh:去掉Synchronize也被否定,而且情况更糟,随之而和的问题更多.互斥、信号量 线程怎么用,能否给个例子?
to lichengbin:我现在用的是DBGrid显示数据,如果要一条一条的显示,那就不能用数据感应控件了,那我不是要一个格子一个格子的赋值上去,而且每一个窗体都有10个查询,又有十多个窗体,那在同时查询的时候,情况不知道能否解决,但是我现在要全部修改的话,工作量就不少,我试试看.
 
当有若干个同类线程对界面的同一个VCL控件进行操作进,必须用Synchronize来同步。
就你的情况来说,设有10个FiveQuery线程进行查询,查询所耗时间约8秒,线程更新界面所需时间大约1秒,这样当你一运行10线程时,前8秒时间界面是可以进行其他操作的,但约8秒后,连续进行10X1即10秒的界面更新,这就会出现10秒左右的“忙沙漏”。
所以,要避免这情况,一是减少并发运行的线程数;二是缩短SynchronizeSource执行时间。优化你的同步更新过程,同时把尽可能的代码写在Execute里。
 
呵呵...那像我上面的那些代码还有得救吗?同步的过程全是关于界面更新的呀.
 
我碰到的问题跟楼主一样,不过把同步部分的代码写到一个线程的EXECUTE里,在更新的时候,创建此更新线程,界面无响应问题就解决了.
 
不是说界面更新在线程是不是安全的吗?这样不会有问题?
 
把界面更新的部分在线程里单独写一个过程,如:
procedure Tprocess_data.show_me;
begin
form1.statusbar1.simpletext:=mtt(mtt为线程里的一个局部变量)
end;
在线程的执行过程里这样写:
...处理数据
mtt:=要显示的信息
Synchronize(show_me);
这样同步过程将非常短,同步只是在主界面显示信息而已,而不是把整个处理过程都写进同步过程中去。。。
 
虽然大家提出的方法还不能解决我的问题,但是至少有一点理解,那就是出现时间漏斗是因为更新界面,更新界面的时间越少,出现漏斗的时间也就越少,那就说,同步过程的代码优化的问题,对不对?:
 
既然不能解决问题,那就结帐吧.谢谢各位了
 
后退
顶部