Call BlockingCollection<T>.Dispose at the end of the program.
Use Task.Run instead of ThreadPool.QueueUserWorkItem.
Use Interlocked to generate product ID and delete the SequentialIdGenerator class.