程序中根据条件创建了数目不定的多个线程通过SOCKET传输远端计算机的信息,请问如何在主线程中随时及时的停止这些线程哪?(如果在创建的线程中加入退出条件,则这些线程非同时退出,拖延时间较久)谢谢!
解决方案 »
- Delphi工程中只知道窗体名称和窗体类名称(字符串名称),能否可以创建窗体?
- TVirtualStringTree使用的几个问题
- 浏览CSDN贴子时总是报"无法显示XML页"错误
- 高分紧急求助,请各位提供IE方面开发的帮助和资料!!!!
- 图片放大问题
- 请问哪位有 HookComm 和 Portmon 的源码啊? 这两个源码都是开放的
- delphi数据库保存的问题!up 有分!
- 请教!用delphi连接数据库问题!弄了一下午,快疯了!拜托了!
- table?
- 我怎么打开远程文本文件(局域网内也行)?急!急!急!
- 请教;怎么取得两个date之间相差的天数?
- DBGRID如何显示计算值--如合计值、序号等
用Threads来保存线程列表
回复人: aquadp(阿凯) ( ) 信誉:100 2002-12-04 15:05:00 得分:0
好像是用线程的terminate方法和free吧,试试
回复人: happyzsl(学习) ( ) 信誉:100 2002-12-04 15:06:00 得分:0
是TThreadList不是Threads,呵呵
回复人: zhxk32899559(小爪)( ) 信誉:100 2002-12-04 15:22:00得分:0
如何保存啊,能举个例子吗?
回复人: moudy(勇士) ( ) 信誉:100 2002-12-04 16:06:00 得分:0
我的偶像。
回复人: moudy(勇士) ( ) 信誉:100 2002-12-04 16:07:00 得分:0
发错了,sorry。
回复人: happyzsl(学习) ( ) 信誉:100 2002-12-04 16:08:00 得分:0
mylist := TThreadList.Create;
mylist.Add(thread1);
mylist.Add(thread2);
...
我没实际用过,你试试看,怎样说一下
回复人: moudy(勇士) ( ) 信誉:100 2002-12-04 16:26:00 得分:0
既然来了就随便说两句吧!不对别砸我。
先把线程缓存起来。在onterminate事件中。
var cache:TThreadlist;
procedure Tmythread.terminate(sender:Tobject);
begin
cache.add(self);
end;
程序需要线程时,调用getthread().看看就知道作用。
function getThread:Tthread;
begin
with cache.locklist do
begin
if count then
begin
result:=TThread(items[0]);
delete(0);
end
else
result:=TmyThread.create(true);
end;
cache.unlocklist;
end;
终止时除掉线程。
procedure ApplicationDeactivate(sender:Tobject);
var i:integer;
begin
with cache.locklist do
begin
for i:=count-1 do
begin
item[i].free;
delete[i];
end;
end;
cache.unlocklist;
end;ok 了。
回复人: zhxk32899559(小爪) ( ) 信誉:100 2002-12-06 08:47:00 得分:0
多谢勇士出手,不过请问为什么在Tmythread.terminate中将线程加入cache哪?
回复人: zhxk32899559(小爪) ( ) 信誉:100 2002-12-06 08:52:00 得分:0
补充一下,所创建的数目不定的多个线程除非满足一定条件,否则一直在循环执行,并不是一次执行完线程就终止。
好像是killThread..你自己找找吧
试下!
TMyThread = class(TThread)
private
FWaker: THandle;
FTimeout: Integer;
protected
procedure Execute; override;
public
property Waker: THandle read FWaker write FWaker;
property Timeout: Integer read FTimeout write FTimeout; constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
end;constructor TMyThread.Create(CreateSuspended: Boolean);
begin
FWaker := CreateEvent(nil, True, False, nil);
inherited Create(CreateSuspended);
end;destructor TMyThread.Destroy;
begin
CloseHandle(FWaker);
inherited;
end;procedure TMyThread.Execute;
begin
while not Terminated do
begin
//do something
WaitForSingleObject(FWaker, FTimeout);
end;
end;//主程序里可以更改MyThread.Waker状态来唤醒线程,如:
MyThread.Terminate;
SetEvent(MyThread.Waker);
果没有空闲的就新建一个)来应用。当然,这些Thread的功能任务是一样的。当任务完成时,Thread自动将自己放回池中,所以TMyThread.OnTerminate中调用cache.add(self),以便下一次使用。这个方法可以节省创建Thread和结束Thread的时间。
如果要在主线程中随时及时地停止这些线程,可以在你的线程的Execute代码中的等待资源的地方,尽量使用WaitForMultipleObjects(Ex),以同时等待主线程的退出信号,一旦等到的是主线程的退出信号,就立即善后,然后调用Terminate;这样,你的主线程可以在需要停止这些线程的时候设置退出信号。
alphax(尽我所知帮助你吧) :你好
勇士说的那种方法不能及时地停止线程以并安全的释放资源吗?
它给的代码编译不过cache.locklis.items[i]没有free方法。
勇士说的那种方法和能不能及时停止线程并安全地释放资源这个问题没有关系,
她只是一种线程缓冲池实现方法,目的只是节省创建和撤销线程的时间。
至于能不能及时停止线程并安全释放资源要看你的Thread的实现
//它给的代码编译不过cache.locklis.items[i]没有free方法。
勇士可能是临时写给你的,自己没有运行过,不过它的大致意思是,仅供参考:====================================================//检取一个空闲的工作线程对象
function RetriveFreeThread: TThread;//等待所有工作线程中止
procedure TerminateWorkingThreads;implementationvar
ThreadPool :TThreadlist;type
TMyThread = class(TThread)
protected
procedure DoTerminate; override;
//procedure Execute; override; //这里自己完成
end;procedure TMyThread.DoTerminate;
begin
ThreadPool.Add(Self); //放回缓冲池
end;function RetriveFreeThread: TThread;
begin
with ThreadPool.LockList do
try
if Count > 0 then
begin
Result := TThread(Items[0]);
Delete(0);
end
else
Result := TMyThread.Create;
finally
ThreadPool.UnlockList;
end;
end;procedure TerminateWorkingThreads;
var
I: Integer;
begin
with ThreadPool.LockList do
try
for I := 0 to Count-1 do
TThread(Items[0]).Terminate;
//虽然调用了Terminate,但是线程们并不一定都立即中止,因为它们还在工作
//或者在等待什么,甚至再无限等待,所以最好就是给它们发信号(使用Win32的
//事件对象)而不只是简单的调用Terminate,而工作线程在有需要无限等待
//(比如监听客户的连接请求)时,应该同时等待主线程的中止信号。
//具体的你可以参考CreateEvent, WaitForMultipleObjects等函数的帮助 for I := 0 to Count-1 do
TThread(Items[0]).WaitFor;
finally
ThreadPool.UnlockList;
end;
end;procedure FreeThreads;
begin
with ThreadPool.LockList do
try
while Count > 0 do
begin
TThread(ThreadPool.Items[0]).Free;
Delete(0);
end;
finally
ThreadPool.UnlockList;
end;
end;initialization
ThreadList := TThreadList.Create;finalization
if ThreadList <> nil then
begin
FreeThreads;
ThreadList.Free;
end;end.
勇士说的那种方法不能及时地停止线程以并安全的释放资源吗?
勇士说的那种方法和能不能及时停止线程并安全地释放资源这个问题没有关系,
她只是一种线程缓冲池实现方法,目的只是节省创建和撤销线程的时间。
至于能不能及时停止线程并安全释放资源要看你的Thread的实现
//它给的代码编译不过cache.locklis.items[i]没有free方法。
勇士可能是临时写给你的,自己没有运行过,不过它的大致意思是,仅供参考:====================================================//检取一个空闲的工作线程对象
function RetriveFreeThread: TThread;//等待所有工作线程中止
procedure TerminateWorkingThreads;implementationvar
FreeThreadPool, WorkingThreads :TThreadlist;type
TMyThread = class(TThread)
protected
procedure DoTerminate; override; procedure Execute; override; //这里自己完成
end;procedure TMyThread.DoTerminate;
begin
with WorkingThreads.LockList do
try
WorkingThreads.Remove(Self);
finally
WorkingThreads.UnlockList;
end; FreeThreadPool.Add(Self); //放回缓冲池
end;procedure TMyThread.Execute;
begin
with WorkingThreads.LockList do
try
Add(Self);
finally
WorkingThreads.UnLockList;
end;
end;function RetriveFreeThread: TThread;
begin
with FreeThreadPool.LockList do
try
if Count > 0 then
begin
Result := TThread(Items[0]);
Delete(0);
end
else
Result := TMyThread.Create;
finally
FreeThreadPool.UnlockList;
end;
end;procedure TerminateWorkingThreads;
var
I: Integer;
begin
with WorkingThreads.LockList do
try
for I := 0 to Count-1 do
TThread(Items[I]).Terminate;
//虽然调用了Terminate,但是线程们并不一定都立即中止,因为它们还在工作
//或者在等待什么,甚至再无限等待,所以最好就是给它们发信号(使用Win32的
//事件对象)而不只是简单的调用Terminate,而工作线程在有需要无限等待
//(比如监听客户的连接请求)时,应该同时等待主线程的中止信号。
//具体的你可以参考CreateEvent, WaitForMultipleObjects等函数的帮助 while Count > 0 do
TThread(Items[0]).WaitFor;
finally
WorkingThreads.UnlockList;
end;
end;procedure FreeThreads;
begin
with FreeThreadPool.LockList do
try
while Count > 0 do
begin
TThread(ThreadPool.Items[0]).Free;
Delete(0);
end;
finally
FreeThreadPool.UnlockList;
end;
end;initialization
FreeThreadList := TThreadList.Create;
WorkingThreads := TThreadList.Create;finalization
if FreeThreadList <> nil then
begin
FreeThreads;
FreeThreadList.Free;
end; WorkingThreads.Free; end.
你好!
我查了一些CreateEnent,与WaitForMultipleObjects的资料,可是由于功力较浅,只能一知半解,也没能找到简单易懂的代码(好多这方面的程序是涉及到通信的)。
能不能给举一个简单的例子哪?谢谢!
一般使用Socket网络通讯的时候,会使用一种组塞模式,当某个套接字阻塞的时候
使用互斥元,或者临界区都是无效的,因为线程已经处于挂起状态。这个时候只有强制关闭该套接字才能使线程激活而达到退出的目的。如果说你的退出耗时不是由于这个原因导致的,那么你就该看看你线程循环怎么写的,尽量是循环一次所耗时间缩短,每次循环判断主线程的退出标志。这个时候可以使用互斥元或者临界区来访问这个标志,不过,既然只有你的主线程会修改这个标志,那么使用互斥元或者临界区都是不必要的,反而浪费时间。
你好,多谢你的帮助,我给你发了条消息,不知你收到了没有?
重叠I/O模式下的命名管道的例子(不好意思,实在是想不到别的不是关于
通讯的例子,而且因为不完整所以我不可能测试过),里面有CreateEvent
和WaitForMultipleObjects的用例:
type
TWorkingThread = class(TThread)
private
fTerminateEvent: THandle;
protected
procedure Execute; override;
public
constructor Create(aTerminateEvent: THandle);
end;const
PipeName = '\\.\pipe\YourPipeNameHere';constructor TWorkingThread.Create(
aTerminateEvent: THandle //主线程创建的、传递给工作线程的中止信号对象
);
begin
inherited Create(True);
fTerminateEvent := aTerminateEvent;
end;procedure TWorkingThread.Execute;
var
hPipe: THandle;
Overlap: TOverlapped;
WhatToWait: array[1..2] of THandle;
begin
//创建命名管道
hPipe := CreateNamedPipe(PChar(PipeName),
PIPE_ACCESS_DUPLEX //双工模式
or FILE_FLAG_OVERLAPPED, //异步I/O模式
PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE, //消息制
4, //最多4个实例,你也只应创建4个TWorkingThread的实例
1024,
1024,
1000,
nil); if hPipe = 0 then
begin
ReturnValue := -1;
Exit;
end; FillChar(Overlap, SizeOf(Overlap), 0);
try
//创建连接完成信号
Overlap.hEvent := CreateEvent(nil,
True, //手动复位方式
False, //初始为没有信号
nil); if Overlap.hEvent = 0 then
begin
ReturnValue := -2;
Abort;
end; while not Terminated do
begin
//异步调用连接
if not ConnectNamedPipe(hPipe, @Overlap)
and GetLastError <> ERROR_IO_PENDING then
begin
ReturnValue := -3;
Abort;
end; WhatToWait[1] := Overlap.hEvent;
WhatToWait[2] := fTerminateEvent; //等待连接完成或者主线程的中止信号到达
case WaitForMultipleObjects(Length(WhatToWait), @WhatToWait,
False, INFINITE) of
WAIT_FAILED: //等待失败
RaiseLastOSError; WAIT_OBJECT_0:
begin
//等到的是客户的连接完成信号
ResetEvent(Overlap.hEvent); //复位信号,这样你可以使用这个信号对象在后面的
//重叠I/O中 ... //可以在这里完成与客户的交互(读写管道)
...
end; WAIT_OBJECT_0 + 1:
begin
//等到的是主线程中止监听连接的信号,马上中止
Terminate;
end;
end;
end;
finally
//释放核心对象
if hPipe <> 0 then
CloseHandle(hPipe);
if Overlap.hEvent <> 0 then
CloseHandle(Overlap.hEvent);
end;
end;