Delphi中向辅助线程传递TStrings对象的方法
传递堆分配TStrings对象地址给Win32线程的实现示例
核心要点
- 堆分配的
TStrings(如TStringList)生命周期由调用者控制,只要线程运行期间对象不被释放,即可安全访问。 CreateThread的lpParameter参数可直接传递对象指针(或包含指针的自定义结构),进程内线程共享虚拟地址空间,指针有效。- 必须提前设置
IsMultiThread := True,让VCL内存管理器切换到多线程安全模式。 TStrings并非线程安全,跨线程访问时需用同步机制(如临界区、事件)保护。
完整代码示例
unit ThreadStringsDemo; interface uses Windows, Classes, SysUtils; implementation // 工作线程函数:等待唤醒信号,操作TStrings对象 function WorkerThread(lpParameter: LPVOID): DWORD; stdcall; type TThreadParams = record TargetStrings: TStrings; WakeEvent: THandle; AccessCS: TRTLCriticalSection; // 用于TStrings的线程同步 end; var Params: ^TThreadParams; begin Params := lpParameter; try while True do begin case WaitForSingleObject(Params^.WakeEvent, INFINITE) of WAIT_OBJECT_0: begin ResetEvent(Params^.WakeEvent); // 临界区保护TStrings访问 EnterCriticalSection(Params^.AccessCS); try Params^.TargetStrings.Add(Format('Thread updated at %s', [DateTimeToStr(Now)])); finally LeaveCriticalSection(Params^.AccessCS); end; end; WAIT_FAILED: begin OutputDebugString('WaitForSingleObject failed'); Break; end; end; end; finally Dispose(Params); end; Result := 0; end; procedure DemoThreadStringPassing; var WorkerStrings: TStrings; ThreadHandle: THandle; ThreadID: DWORD; Params: ^TThreadParams; WakeEvent: THandle; AccessCS: TRTLCriticalSection; begin // 启用VCL多线程内存管理器 IsMultiThread := True; // 初始化临界区 InitializeCriticalSection(AccessCS); try // 创建堆上的TStrings对象 WorkerStrings := TStringList.Create; try // 创建唤醒事件(手动重置,初始无信号) WakeEvent := CreateEvent(nil, True, False, nil); if WakeEvent = 0 then begin Writeln('Failed to create wake event'); Exit; end; try // 分配线程参数(堆分配,避免栈变量生命周期问题) New(Params); Params^.TargetStrings := WorkerStrings; Params^.WakeEvent := WakeEvent; Params^.AccessCS := AccessCS; // 创建工作线程 ThreadHandle := CreateThread(nil, 0, @WorkerThread, Params, 0, ThreadID); if ThreadHandle = 0 then begin Writeln('Failed to create worker thread'); Dispose(Params); Exit; end; try // 调用端交互逻辑:触发线程更新或退出 Writeln('Press Enter to trigger thread update; type "quit" to exit'); while True do begin var InputLine: string; Readln(InputLine); if UpperCase(InputLine) = 'QUIT' then Break; // 触发线程执行更新 SetEvent(WakeEvent); // 安全读取TStrings内容(临界区保护) EnterCriticalSection(AccessCS); try Writeln('Current string count: ', WorkerStrings.Count); for var I := 0 to WorkerStrings.Count - 1 do Writeln(' ', WorkerStrings[I]); finally LeaveCriticalSection(AccessCS); end; end; // 终止线程(实际项目建议用优雅退出标志,TerminateThread为简化示例) TerminateThread(ThreadHandle, 0); finally CloseHandle(ThreadHandle); end; finally CloseHandle(WakeEvent); end; finally WorkerStrings.Free; end; finally DeleteCriticalSection(AccessCS); end; end; end.
关键细节说明
- 参数传递方式:示例用堆分配的
TThreadParams结构传递多个参数(TStrings指针、唤醒事件、临界区),如果仅需传递TStrings,可直接将WorkerStrings作为lpParameter传入,线程函数内转换为TStrings(lpParameter)即可。 - 线程安全保护:通过临界区
TRTLCriticalSection确保调用者和线程不会同时修改/读取TStrings,避免数据损坏。 - 对象生命周期:TStrings对象由调用者创建和释放,线程仅负责访问,需保证线程运行期间对象不被提前释放。
- 线程唤醒逻辑:用
CreateEvent创建的事件控制线程唤醒,符合“无限等待填充”的需求,调用者通过SetEvent触发线程执行更新操作。
内容的提问来源于stack exchange,提问作者WayOfTheWright
相关产品推荐
相关产品推荐

