A long running task is one that may enter a waiting state, blocking the thread it runs on, or one that takes too much CPU time (we'll come back to this one).
Some may say this definition is too broad, many tasks would be long running, but think about it, even if the wait is bounded to a small timeout, the task is still not using the CPU effectively. If the amount of these tasks rises, you'll observe they don't scale linearly past the MinWorkerThreads (see ThreadPool.SetMinThreads
), the degradation is really bad.
The approach it to switch all I/O (file, network, DB, etc.) to be asynchronous.
There are also long running tasks due to long CPU-intensive computations.
The approach is to defer computation, such as inserting await Task.Yield()
at certain points, or preferably deferring computation explicitly by scheduling one task after the other, each processing a previously split chunk of data or process a buffer up to a bounded time limit.
The "too much time" is up to you to decide.
When you're in an environment where you're sharing the thread pool, any time is too much time, you must choose a sensible value.
E.g. in ASP.NET under IIS, see what is the average time taken per request for the most common requests. Similarly, in a service where the thread pool is used e.g. for processing a message queue, take the average per message.
More generally, "too much time" is when work items are queued faster than they're processed. There may be bursts of work, so you should average this over the time unit that matters to you, be it a second, a minute, 10 minutes, etc. When you have an SLA, you should have this interval defined somewhere.
After having a sensible value, you must see, in practice, if it's OK to increase it or if you must decrease it. More often, if you may increase it, you're better off not increasing it, unless you can see a significant performance difference. "Significant" means the number of processed items increase more than linearly, so if it's linear (or below linear, it can happen), don't do it.
In my experience, if you have a long running task by any of these definitions, you're usually better off with managing your own thread or set of threads.
Task
world when you need to choose betweenThreadPool.QueueUserWorkItem
andnew Thread
. – MisquoteLongRunning
, unless it's really long running (either same long as application living time, close to that or relatively long task job has to be completed). – Arc