Although nowadays people, including me, are working mostly with tasks and async/await, sometimes going one level lower is helpful, because there’s less to worry about. And as I was today calling trusty
ThreadPool.QueueUserWorkItem I found new overload. Overload that is generic.
Since the very beginning the
object as a state that was passed to the
WaitCallback delegate provided. That means if you passed value type, it was boxed and you then had to cast it back in the delegate. Boxing is not a great for performance (allocations) and casting is easy to mess up, especially when refactoring.
As it turned out, since in .NET Core 2.1 the method has a new generic overload
bool QueueUserWorkItem<TState>(Action<TState> callBack, TState state, bool preferLocal). In .NET Standard it’s “only” starting from 2.1. Here is the interesting commit from Stephen Toub. This means both of the above-mentioned problems are not longer an issue.
What is the
preferLocal parameter for? It allows you to queue the work item into thread pool thread’s local queue compared to default behavior of going into global queue. That, in some scenarios, reduces contention on the global queue, improves cache locality or takes advantage of work stealing and probably some other things.
While I can use this overload today with .NET 2.1 or 2.2, it’s sad it didn’t make it into .NET Standard 2.0. On the other hand, all the performance goodness’s (like well-known
Span<T>) are in .NET Standard 2.1 anyway, so this one is only a drop in the ocean.
UnsafeQueueUserWorkItem has this new overload as well.