Delphi通过线程类TThread 极大地简化了windows的多线程API函数操作。但是TThread 对象是没有实例的。它和界面交流主要靠主线程。那么核心问题就是线程的同步了。
一、线程与主线程同步方式常用的2种:
1、使用Synchronize方法(这个方法用于访问VCL 主线程所管理的资源)
procedure Theater.Execute;
begin
Synchronize(DoS);
end;
procedure Theater.DoS;
begin
.........
end;
2、使用消息(这个方法也可用于进程之间的通信)
主窗口定义一个消息
const MSG_DTSCROLL = WM_USER + 2020;
procedure MsgDtScroll(var Msg: TMessage); message MSG_DTSCROLL;//声明
procedure TMainF.MsgDtScroll(var Msg: TMessage);
begin
........
end;
线程发送消息
procedure Theater.Execute;
begin
PostMessage(Handle, MSG_DTSCROLL, 0, 0);
end;
另外还有些控件对象内部提供了线程的同步机制,如TCanvas可以使用其提供的Lock方法用于线程的同步
上面解决了线程和主线程同步问题,可是如果有2个线程同时访问一个控件应该如何处理。使用临界区就可以解决这个问题
二、线程同步之临界区
uses SyncObjs;
var
CS: TCriticalSection; //界面创建时要初始化 界面销毁时要释放
function MyThreadFun(p: Pointer): DWORD; stdcall;
var
i: Integer;
begin
CS.Enter;
for i := 0 to 99 do Form1.ListBox.Items.Add(IntToStr(i));
CS.Leave;
Result := 0;
end;
另外已经启动的线程,我们如何检测执行状态,来判断是否做其他操作。
三、检测线程执行状态
//返回值:0-已释放;1-正在运行;2-已终止但未释放;3-未建立或不存在
function CheckThreadFreed(aThread: TThread): Byte;
var
I: DWord;
IsQuit: Boolean;
begin
if Assigned(aThread) then
begin
IsQuit := GetExitCodeThread(aThread.Handle, I);
if IsQuit then
begin
if I = STILL_ACTIVE then Result := 1
else Result := 2;
end else Result := 0;
end else Result := 3;
end;
四、其他注意事项
1.如果用到了ado控件需要使用CoInitialize(nil);初始化线程环境,线程结束前调用CoUninitialize();
2.线程类默认创建即启动,不启动创建时xxx.create(true);
3.线程类属性FreeOnTerminate设为true执行完就释放;
网友评论