Correct me if I'm misreading your question but my understanding is that when users do the call in question, it involves some kind of potentially lengthy I/O.
Threads are not a good choice if all you're doing is waiting for a result of some kind. Creating additional threads is mostly good for CPU-bound work but the advantage of using them is much less clear if all you're doing is waiting for something to happen.
You really need to replace this with some kind of asynchronous or non-blocking I/O.
My standard illustration of this fact is as follows: suppose you go a restaurant with 10 people. When the waiter comes by, the first person he asks for his order isn't ready; however, the other 9 people are. Thus, the waiter asks the other 9 people for their orders and then comes back to the original guy hoping he'll be ready to order by then. (It's definitely not the case that they'll get a second waiter to wait for the original guy to be ready to order and doing so probably wouldn't save much time anyway). That's how async/await works in many cases (the exception being that some of the Task Parallel library calls, like Thread.Run(...), actually are executing on other threads - in our illustration, bringing in a second waiter - so make sure you check the documentation for which is which).
The case where you'd want multiple waiters is for tasks that are truly "waiter-bound" (i.e. where the waiter would be the primary holdup for the task). For example, if your restaurant has 100 tables it wouldn't be smart to have a single waiter try to service all of them, nor would it be smart to also have the waiter also prepare the food once he takes the orders. In these cases, you'd want to have a separate person to cook the food and several waiters. Eventually you might want multiple cooks too and maybe busboys, etc. This is a case where you'd have multiple threads; generally, the threads would serve specialized roles (e.g. waiters, busboys, cooks, etc.) and would "divide up" work that fit into their particular category (e.g. each waiter would work several tables).
For your particular application, though, even if you do create a new thread to handle each user, there are much better ways of doing what you want than continuously polling for a result using while
and Thread.Sleep
, such as the ManualResetEvent class, which allows you to block a thread (or group of threads) until a particular event has happened (thus eliminating the need for a polling loop).