Glad that worked for you.
The doThreadInvoke call should still be using the IS Service Manager to invoke the services, so it will consume service threads in exactly the same way as any other mechanism e.g. triggers or an HTTP call.
Someone else may be able to help you on the second part of your question, as I’m not sure which thread pool the thread is going to come from. So if the initial invocation is through the HTTP port, is the asynchronously invoked thread going to to be taken from that pool or the general service thread pool configured for the entire IS? If you’ve got your test running, it’s probably easy enough to confirm - just create a HTTP port with very few threads available (say 3 or 4) and try to spawn more threads.
If I was guessing (and I am), I’d expect the thread to come out of the general thread pool not the pool for the HTTP port because you are operating below the HTTP processor. I’d expect similar if the top level service was invoked through the trigger (the extra threads would not come out of the trigger thread pool i.e. concurrency level).
In this case, you’ll need to either manage the concurrency yourself, or ensure that the server threads setting is high enough for desired level of concurrency (and by implication, that your HTTP thread pool is small enough that the achieved level of concurrency is acceptable for your JVM and infrastructure). Easy enough - max asynch invocations per thread times the number of threads in the HTTP thread pool is how many threads you could in theory consume at any one time.
Regarding side-effects - you can introduce as many side-effects as you’d like. Seriously, working inside the service thread and invoking IS services will offer a certain amount of protection, but exercise the usual care associated with concurrent invocations, including any necessary checks for locking, dead-locking, shared access to data, timing, time-out, error handling, orphaned threads, etc.