4

How to pass LongRunning flag specifically to Task.Run()? highlights that it can be a little messy to get Task creation flags into the newer APIs especially using the async pattern.

And I found this article claiming it's not a great idea with async anyway and shouldn't be used: http://blog.i3arnon.com/2015/07/02/task-run-long-running/

My understanding is that this flag in practice will cause TPL to spin up a dedicated thread rather than stressing the threadpool but particularly if my application doesn't involve lots of parallel tasks, is it really a big deal? Can I safely omit the flag if my expected parallelism is less that the default threadpool size (whatever that is) - is the worst that happens the threadpool might be starved of threads for a few hundred milliseconds anyway?

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • 1
    It won't break completely if you ignore it, but if you do saturate the threadpool it might take longer before additional threads are spun up to handle new tasks. Is there a reason you **don't want to** pass this value? Always when I see people asking "I want to avoid doing X, is it safe?" my immediate question is always "Why do you want to avoid doing X?". – Lasse V. Karlsen Feb 10 '20 at 08:55
  • `in practice will cause TPL to spin up a dedicated thread` - [this answer](https://stackoverflow.com/a/26931368/11683) from your link explains that it won't. Also probably see https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html that discusses `LongRunning` in item 3. – GSerg Feb 10 '20 at 09:31
  • @GSerg the link you quoted doesn't contradict OP's claim that currently the TPL honors the `LongRunning` flag by spinning up a dedicated thread. It is just not guaranteed that this behavior will remain the same for ever. The probability that some day Microsoft will revise the behavior of the decade-old API is anyone's guess. My guess is: the probability is pretty low. – Theodor Zoulias Feb 10 '20 at 11:10
  • 1
    When you ask "Can I safely ignore the flag" do you mean "Can I safely omit the flag"? – Theodor Zoulias Feb 10 '20 at 11:16
  • @TheodorZoulias indeed, corrected – Mr. Boy Feb 10 '20 at 11:51
  • @LasseV.Karlsen mainly just because the code is ugly, and the API suggests MS don't really consider it important since they do not provide a way to pass the flags in the newer APIs. – Mr. Boy Feb 10 '20 at 11:52

2 Answers2

5

The LongRunning flag is omitted by default when calling the Task.Factory.StartNew method without passing the TaskCreationOptions argument, so you can safely assume that omiting it is safe. Actually it is more safe to omit it than to include it, since this flag is intended as a performance optimization technique, not as an everyday commodity.

In general, don't use it unless you find that you really need it. You'd typically only use LongRunning if you found through performance testing that not using it was causing long delays in the processing of other work. (citation)

In case that the ThreadPool is routinely starved because its threads are misused (are blocked while waiting for I/O operations to complete), then instead of decorating all of your Tasks with the LongRunning flag, a simpler and more efficient workaround could be to increase the minimum number of ThreadPool threads with the method ThreadPool.SetMinThreads during the initialization of your application. For example:

ThreadPool.SetMinThreads(workerThreads: 100, completionPortThreads: 5);

It will be easier to undo this hack when you refactor your application to use asynchrony correctly, instead of undoing the LongRunning flag everywhere in your code.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
1

The whole idea behind Thread Pool is that creating task take some milliseconds, because it asks OS to create it, switch contexts and so on and so on... so to deal with it, Framework create some pool, and keep used threads there for later use...

You are right, LongRunning flag most probably will cause new thread creation... this make sense when new task is going to take longer and Thread creation time is not significant in it.

Threadpool has certain algorithms, if you take lots of threads from there intensively and keep them busy, it may decide to double the amount of threads assuming that you are going to take more and more ... so if you are going to take threads from Thread Pool busy long enough, you will not get any benefit from ThreadPool, but instead you get some overhead.

So ignoring that flag will not break anything, but may bring some overheads.

Arsen Mkrtchyan
  • 49,896
  • 32
  • 148
  • 184
  • Which kind of has the corollary that in a small application where we aren't using lots of threads or performance simply isn't an issue, it's safe - but perhaps should be commented/documented as such. Or we just do it the 'proper' way. – Mr. Boy Feb 10 '20 at 11:54