You are accessing
VCL from execute ?!!!!!!!!!!!!
That is wrong, and must not be done.
Sebastian had spend his time writing you a working and correct example to build upon, that doesn't call and use VCL element from background thread, it is to the point and will serve you quite well, re-use his code.
the only thing i prefer in his code to switch to blocking instead of using Sleep(1),
@AJ_Oldendorf, the following is not for you for now:
Sleep(1) in tight loop will in best case scenario will cause 50 (to be accurate 64) context switch and that if the time period is default at 1000/64=15.625ms, in worst case when time period is 1, this will cause 1000 context switch per socket !, that is just a waste of CPU cycles, as this loop will continue as long the operation alive, even if modern CPU will
handle this like nothing and Process Explorer will report this usage in %0.01 CPU usage, it is still waste cycles. Also on server expecting a hundred connection or even thousands, any application on the server can change this period and raising the context switch to what ! a million,
Best approach handling IO operation is asynchronous IO ( overlapped, IOCP ..) , the next is blocking, then lastly the worst of them is looping over poll and sleep/switch.
here a screen shot from this moment, my device is running long test for an application that utilize %25 (one core) with only 3 threads for hours now, also the
IDE is opened, two browser (LibreWOlf and Supermium) with thunderbird, look at the context switch delta with how many threads are running.

For me that is healthy
OS with healthy applications behavior.