Threads can't take arguments, I forget why - probably something to do with having them able to be run in the IDE. The only way that immediately occurs to me is to have a different Thread Sub for each simultaneous connection that you want and pick the IPaddress from somewhere known to each individual Sub.
B4X:
Thread1.Start("Main.Thread1")
Thread2.Start("Main.Thread2")
Thread3.Start("Main.Thread3")
Sub Thread1
ThreadCommon("1.2.3.4") ' get the address from somewhere
End Sub
Sub Thread2
ThreadCommon("1.2.3.5") ' get a different address from somewhere
End Sub
Sub Thread31
ThreadCommon("1.2.3.6") ' get a different address from somewhere
End Sub
Sub ThreadCommon(IPaddress)
.... ' using Locals is OK but beware of any Globals
End Sub
I'm not entirely sure if this might be helpful to you, but here's a rudimentary example of a threadsafe stack. The idea is that you can push your Ips into the stack and then pop them when dynamically creating the clients. You could make a second stack to push failed connects into and have that periodically handled again.
Thanks for your efforts agraham and Basic4Life; but your Stack is already implemented in Andrew's Collections library. I've decided to use the QueueEx from the Collections library instead - it acts as a FiFo instead of pushing and pulling from a Stack - and initial tests look good.
But it's not threadsafe, and neither is QueueEx. Basic4life is correct that whichever you use should be made threadsafe in your scenario. If you want a synchronised Queue you can do it in a similar way to his Stack example.
Actually if you are going to do more than one operation that requires exclusive uninterrupted access to the Stack or Queue, e.g. checking whether the Stack or Queue is not empty before Popping it then you should use StackEx or QueueEx and do your own locking as the .NET 2.0 Synchronized collections only lock individual methods and not multiple operations. See this multithreading discussion