title: C# Parallel.ForEach Does Not Wait Until Finished
body: <p>I am a beginner at this thread thing and I have been hitting my head against the wall for two days. I read everywhere the Parallel.ForeEach will wait until the threads are finished before it comes out of the ForEach. I am here to tell you that is a bunch of you know what. This will just set up a bunch of tasks as scheduled and drop out of the ForEach.</p>
  
  <p>So my questions are, how do I make the tasks go from scheduled to run? How do I keep in the program until completing all of the threads? This example I have below, it will just schedule the tasks and drop out of the program.</p>
  
  <p>BTW, I stole the encryption part from another StackOverflow post just to give an example of a task that would take some time.</p>
  
  <p>Edit - it was suggested I include a reference to the encryption code I pasted in and it is a good idea. I believe it is originally from Microsoft, but their answer is here (<a href="https://stackoverflow.com/a/273499/1352794">https://stackoverflow.com/a/273499/1352794</a>).</p>
  
  <p>Edit v2 - I have been playing around with this a bunch and using the help here (thank you) I have come up with:</p>
  
  <pre><code>            Parallel.ForEach(tasks, new ParallelOptions { MaxDegreeOfParallelism = 4 }, task =&gt;
              {
                  task.Start();
                  task.Wait();
                  Console.WriteLine(task.Status);
              });
  </code></pre>
  
  <p>It looks like the "Start" and "Wait" are VERY important to this. With those two commands, it is now working. I am trying to make it so this runs on a maximum of 4 threads, and I am having a hard time making sure that is the case. Any suggestions? I also hope this is the correct way to take a bunch of tasks and push them on to multiple threads.</p>
  
  <pre><code>class Program
  {
      static void Main(string[] args)
      {
  
          List&lt;Task&gt; tasks = new List&lt;Task&gt;();
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
          tasks.Add(new System.Threading.Tasks.Task(() =&gt; DoEncryption()));
  
          bool testbool = Parallel.ForEach(tasks, new ParallelOptions { MaxDegreeOfParallelism = 4 }, myTest =&gt;
          {
              System.Threading.Tasks.Task.Run(() =&gt; myTest);
              Console.WriteLine(myTest.Status);
          }).IsCompleted;
  
          Console.WriteLine("The parallel status is " + testbool);
          string mymessage = System.Diagnostics.Process.GetCurrentProcess().Threads.Count.ToString();
      }
  
      private static void DoEncryption()
      {
          try
          {
  
              string original = "Here is some data to encrypt!";
  
              // Create a new instance of the RijndaelManaged 
              // class.  This generates a new key and initialization  
              // vector (IV). 
              using (RijndaelManaged myRijndael = new RijndaelManaged())
              {
  
                  myRijndael.GenerateKey();
                  myRijndael.GenerateIV();
                  // Encrypt the string to an array of bytes. 
                  byte[] encrypted = EncryptStringToBytes(original, myRijndael.Key, myRijndael.IV);
  
                  //Display the original data and the decrypted data.
                  Console.WriteLine("Original:   {0}", original);
              }
  
          }
          catch (Exception e)
          {
              Console.WriteLine("Error: {0}", e.Message);
          }
      }
      static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
      {
          // Check arguments. 
          if (plainText == null || plainText.Length &lt;= 0)
              throw new ArgumentNullException("plainText");
          if (Key == null || Key.Length &lt;= 0)
              throw new ArgumentNullException("Key");
          if (IV == null || IV.Length &lt;= 0)
              throw new ArgumentNullException("IV");
          byte[] encrypted;
          // Create an RijndaelManaged object 
          // with the specified key and IV. 
          using (RijndaelManaged rijAlg = new RijndaelManaged())
          {
              rijAlg.Key = Key;
              rijAlg.IV = IV;
  
              // Create a decryptor to perform the stream transform.
              ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
  
              // Create the streams used for encryption. 
              using (MemoryStream msEncrypt = new MemoryStream())
              {
                  using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                  {
                      using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                      {
  
                          //Write all data to the stream.
                          swEncrypt.Write(plainText);
                      }
                      encrypted = msEncrypt.ToArray();
                  }
              }
          }
  
  
          // Return the encrypted bytes from the memory stream. 
          return encrypted;
  
      }
  
  }
  </code></pre>