高手请进,问了很多次,没得到很确定答案,关于多线程处理的流程问题,老是怀疑有错 ( 积分: 20 )

  • 主题发起人 主题发起人 zhaoxueli
  • 开始时间 开始时间
Z

zhaoxueli

Unregistered / Unconfirmed
GUEST, unregistred user!
从socket上不停接收数据然后创建线程来处理,做法如下

type //先声明TThread类
TInitThread = class(TThread)
protected
procedure Execute; override;
public
constructor Create;
end;


var
NewThread: TInitThread; //声明线程对象
implementation



constructor TInitThread.Create;
begin
inherited Create(FALSE); //Createsuspended = false
FreeOnTermiNate := True;
end;

procedure TInitThread.Execute; //重载execute
begin
Synchronize(DealData);
end;


procedure DealData();
begin
//处理数据,这里有查数据库,并需要较长时间
end;

Procedure TForm1.SocketRecv(); //在这里接收socket的数据
begin
GLogCS.Enter; //这是线程同步:GLogCS: TCriticalSection;
signlist.Add(recvstr);//把收到的数据先添加到一个list数组上
GLogCS.Leave;
NewThread := TInitThread.Create; //创建新线程
end;

我的问题是:
1、我的这种做发有问题吗?
2、在接收数据时,数据量很大,不停有数据进来,那我就不停的:
NewThread := TInitThread.Create;
这样总好象处理不过来,因为数据量小我发现程序没问题,量一大就不对劲了,form
反应变得很慢,而且form都拖不动了,程序变的很慢
 
从socket上不停接收数据然后创建线程来处理,做法如下

type //先声明TThread类
TInitThread = class(TThread)
protected
procedure Execute; override;
public
constructor Create;
end;


var
NewThread: TInitThread; //声明线程对象
implementation



constructor TInitThread.Create;
begin
inherited Create(FALSE); //Createsuspended = false
FreeOnTermiNate := True;
end;

procedure TInitThread.Execute; //重载execute
begin
Synchronize(DealData);
end;


procedure DealData();
begin
//处理数据,这里有查数据库,并需要较长时间
end;

Procedure TForm1.SocketRecv(); //在这里接收socket的数据
begin
GLogCS.Enter; //这是线程同步:GLogCS: TCriticalSection;
signlist.Add(recvstr);//把收到的数据先添加到一个list数组上
GLogCS.Leave;
NewThread := TInitThread.Create; //创建新线程
end;

我的问题是:
1、我的这种做发有问题吗?
2、在接收数据时,数据量很大,不停有数据进来,那我就不停的:
NewThread := TInitThread.Create;
这样总好象处理不过来,因为数据量小我发现程序没问题,量一大就不对劲了,form
反应变得很慢,而且form都拖不动了,程序变的很慢
 
补充:
procedure DealData();
begin
//处理数据,这里有查数据库,并需要较长时间
end;


处理的就是socket收到的先添加到 signlist上的数据
 
TInitThread.Create(false);
 
同步时间太长了.
 
那怎么办?有没有好的解决办法?
 
当线程过多的时候,线程调度就会占用相当大的系统处理能力,你这种情形应该使用线程池机制,创建固定数量的线程。
 
你这样只会使系统更无效率!
1> 为每个响应创建一个线程, 太耗资源了, 系统不快反而慢.
Procedure TForm1.SocketRecv(); //在这里接收socket的数据
begin
GLogCS.Enter; //这是线程同步:GLogCS: TCriticalSection;
signlist.Add(recvstr);//把收到的数据先添加到一个list数组上
GLogCS.Leave;
NewThread := TInitThread.Create; //创建新线程
end;

2> DealData 实际是在主进程中执行的,你通过同步去执行,比把代码全部写在主进程中更慢!
procedure TInitThread.Execute; //重载execute
begin
Synchronize(DealData);
end;

3> 你的线程同步,我无法理解它做了什么.

你倒不如 SocketRecv(); 把数据不断写入 Signlist, 只开一个线程,这个线程 不断在 Singlist.First 中取数处理后 Singlist.Delete(0); 不要用 Synchronize,Synchronize是将代码在主进序执行的。

procedure TInitThread.Execute;
begin
while not Terminated do
begin
try
//接收主进程的消息
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
begin
if (Msg.message = WM_QUIT) then
Break;
//Self.Terminate;
if (Msg.message = WTM_DATA_NUM) then //自定义消息
begin
//自定义消息的处理过程
WtmDataNum(Msg.wParam);
end;
//将处理后的消息发回Windows,由Windows自己处理,
//DispatchMessage()
end;

if FTaskTList.Count > 0 then
begin
//先进先出
try
DealData(TMyType(Singlist.First));
finally
try
Dispose(Singlist.First);
Singlist.Delete(0);
except
end; //try
end; //tyr
end
else
begin
//4> 利用空闲的时间进行一些常规工作
...
Sleep(50);
end;
except
raise Exception.Create('服务响应线程出现异常情况,已终止执行任务退出');
end;
end; //while
finally
//清除垃圾
end;
end;
 
感谢Pc 狂迷!
(1).只是还不能看的太懂你的代码,我想改成这样行吗?
socket接收还是先放到数组:
GLogCS.Enter; //这是线程同步:GLogCS: TCriticalSection;
signlist.Add(recvstr);//把收到的数据先添加到一个list数组上
GLogCS.Leave;
(2)在form.create时创建一个线程来处理
procedure TForm1.FormCreate(Sender: TObject);
begin
NewThread := TInitThread.Create; //创建新线程
end;
(3)在线程中一直检查 signlist上的数据,不为空就一直处理
procedure TInitThread.Execute;
begin
while not Terminated do
begin
if (Msg.message = WM_QUIT) then //退出条件
Break;
if signlist.count>0 then
begin
....逐一取出处理
end;
end;
end;
(4)那这里就不要自动停了
constructor TInitThread.Create;
begin
inherited Create(FALSE); //Createsuspended = false
// FreeOnTermiNate := True;//这句就不要了
end;
 
这两句按你的用法,放在主进程中是没意义的
GLogCS.Enter; //这是线程同步:GLogCS: TCriticalSection;
GLogCS.Leave;
 
procedure TInitThread.Execute;
begin
while not Terminated do
begin
if (Msg.message = WM_QUIT) then //退出条件
Break;
if signlist.count>0 then
begin
....逐一取出处理
end;
end;
end;
上面的这种方式可行吗?
另外,如过我改成下面的处理方法:
用定事器来以直检查signlist.count,如果有数据就处理,每次取第一条,处理完就删第一条,可行吗?效率会不会很差?
 
写个模拟数据生成器 来测试测试看看,没试过我也下不了定论.
 
学学indy的多线程处理方法,真是设计得很完美
 
我用的Socket接收控件就是INDY的IdTcpServer,主要是我接收的数据量很大,而且每条收到的都要处理,比如写数据库等,有的还挺耗时,这样不用线程能行吗?
 
能否讨论一下用定时器处理是否有问题?
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
579
import
I
后退
顶部