One solution is from the excellent Threading in C# E-book.  In their section on basic structures, the author makes almost exactly what you're looking for in an example.
Follow that link and scroll down to Producer/consumer queue.
In a later section, he addresses that while ConcurrentQueue would work fine too, it performs worse in all cases EXCEPT in highly-concurrent scenarios.  But for your low-load case, it may be better just to get something working easily.  I don't have personal experience with the claim from the document, but it's there for you to evaluate.
I hope this helps.
Edit2: upon Evk's suggestion (thanks!), the BlockingCollection class looks like what you want.  By default it uses a ConcurrentQueue under the hood.  I particularly like the CompleteAdding method, as well as the ability to use CancellationTokens with it.  "Shutdown" scenarios are not always correctly accounted for when things are blocking, but this does it right IMO.
Edit 3: As requested, a sample of how this would work with a BlockingCollection.  I used the foreach and GetConsumingEnumerable to make this even more compact for the consumer side of the problem:
using System.Collections.Concurrent;
private static void testMethod()
{
  BlockingCollection<Action> myActionQueue = new BlockingCollection<Action>();
  var consumer = Task.Run(() =>
  {
    foreach(var item in myActionQueue.GetConsumingEnumerable())
    {
      item(); // Run the task
    }// Exits when the BlockingCollection is marked for no more actions
  });
  // Add some tasks
  for(int i = 0; i < 10; ++i)
  {
    int captured = i; // Imporant to copy this value or else
    myActionQueue.Add(() =>
    {
      Console.WriteLine("Action number " + captured + " executing.");
      Thread.Sleep(100);  // Busy work
      Console.WriteLine("Completed.");
    });
    Console.WriteLine("Added job number " + i);
    Thread.Sleep(50);
  }
  myActionQueue.CompleteAdding();
  Console.WriteLine("Completed adding tasks.  Waiting for consumer completion");
  consumer.Wait();  // Waits for consumer to finish
  Console.WriteLine("All actions completed.");
}
I added in the Sleep() calls so that you can see that things are added while other things are being consumed.  You can also choose to launch any number of that consumer lambda (just call it an Action, then launch the Action multiple times) or the addition loop.  And at any time you can call Count on the collection to get the number of tasks that are NOT running.  Presumably if that's non-zero, then your producer Tasks are running.