I don't know about "best" - depends what your criteria are. If you expand a little on your requirements, we could maybe offer more specific help. In the meantime...
The simplest method is to allow the owning object to write the request to the thread, either into one or more properties or by a public method. The data fields behind the properties/method are not accessed directly by the main Execute routine: use a method called by Synchronize() to copy these data fields into variables that can be used by the Execute() routine. I use this method when speed is not the main objective, and the owning object does not need to queue multiple requests.
Many people disparage using Synchronize, but it depends on the functionality you are trying to achieve. I try to keep things simple until the requirements demand otherwise.
If throughput is more of an issue, or if you need to have overlapping requests, you could use a queue to store the requests, with access to the queue controlled by a TCriticalSection. You could also use TThreadList, either directly or as a basis for your own typed storage - I am not aware of a generic equivalent of TThreadList, though there may well be one.