Monday, June 2, 2014

Spin up two threads in C# and wait for them both to finish before proceeding.

I opened up C# 4.0 in a Nutshell by Joseph and Ben Albahari again today. In stared at pages 833 and 835 and then wrote this:

using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Web.Mvc;
namespace YingYang.Controllers
{
   public class HomeController : Controller
   {
      static EventWaitHandle _waitForYing = new AutoResetEvent(false);
      static EventWaitHandle _waitForYang = new AutoResetEvent(false);
      private const int _yingSleep = 3000;
      private const int _yangSleep = 4000;
      
      public ActionResult Ying()
      {
         new Thread(Yang).Start();
         using (Stream x = new FileStream(@"C:\Apps\YingYang\ying.txt",
               FileMode.Append))
         {
            byte[] foo = ASCIIEncoding.ASCII.GetBytes(DateTime.Now.ToString() + "\r\n");
            x.Write(foo, 0, foo.Length);
            Thread.Sleep(_yingSleep);
            byte[] bar = ASCIIEncoding.ASCII.GetBytes(DateTime.Now.ToString() + "\r\n");
            x.Write(bar, 0, bar.Length);
            Thread.Sleep(_yingSleep);
            byte[] baz = ASCIIEncoding.ASCII.GetBytes(DateTime.Now.ToString() + "\r\n");
            x.Write(baz, 0, baz.Length);
            Thread.Sleep(_yingSleep);
            byte[] qux = ASCIIEncoding.ASCII.GetBytes(DateTime.Now.ToString() + "\r\n");
            x.Write(qux, 0, qux.Length);
            Thread.Sleep(_yingSleep);
         }
         _waitForYing.Set();
         _waitForYang.WaitOne();
         return View(DateTime.Now);
      }
      
      static void Yang()
      {
         using (Stream x = new FileStream(@"C:\Apps\YingYang\yang.txt",
               FileMode.Append))
         {
            byte[] foo = ASCIIEncoding.ASCII.GetBytes(DateTime.Now.ToString() + "\r\n");
            x.Write(foo, 0, foo.Length);
            Thread.Sleep(_yangSleep);
            byte[] bar = ASCIIEncoding.ASCII.GetBytes(DateTime.Now.ToString() + "\r\n");
            x.Write(bar, 0, bar.Length);
            Thread.Sleep(_yangSleep);
            byte[] baz = ASCIIEncoding.ASCII.GetBytes(DateTime.Now.ToString() + "\r\n");
            x.Write(baz, 0, baz.Length);
            Thread.Sleep(_yangSleep);
            byte[] qux = ASCIIEncoding.ASCII.GetBytes(DateTime.Now.ToString() + "\r\n");
            x.Write(qux, 0, qux.Length);
            Thread.Sleep(_yangSleep);
         }
         _waitForYing.WaitOne();
         _waitForYang.Set();
      }
   }
}

 
 

ying.txt ended up with this in it when I ran the app I made:

6/2/2014 6:01:00 PM
6/2/2014 6:01:03 PM
6/2/2014 6:01:06 PM
6/2/2014 6:01:09 PM

 
 

yang.txt ended up with this in it when I ran the app I made:

6/2/2014 6:01:00 PM
6/2/2014 6:01:04 PM
6/2/2014 6:01:08 PM
6/2/2014 6:01:12 PM

 
 

The DateTime value which makes it into the view ends up being coughed up as a string to the user and it looks like this:

6/2/2014 6:01:16 PM

 
 

If _yangSleep is set to 2000 instead, the application doesn't behave appreciably different. Both text files will still end up with dates in them which come before the date that ends up making its way into the UI's HTML. Both threads finish their file I/O mechanics before this line of code is ever run:

return View(DateTime.Now);

 
 

This outcome will happen without regard to which thread is speedier in getting its work done.

No comments:

Post a Comment