Archive

Posts Tagged ‘Threading’

Basic Thread Coordination Part 1

November 23, 2010 Leave a comment

When threads are created they run interdependently from the thread that created them. This is exactly what we want. However we often need to wait for multiple threads doing work to finish before continuing. This is done with the Join() method on the thread which blocks the main thread while waiting till the thread completes.

using System;
using System.Threading;

namespace ThreadsAreForScheduling
{

    public static class ThreadExtensions
    {
        public static void JoinAll(params Thread[] threads)
        {
            Array.ForEach(threads, thread => thread.Join());
        }

        public static void JoinAll(TimeSpan timeout, params Thread[] threads)
        {
            Array.ForEach(threads, thread => thread.Join(timeout));
        }
    }

    public class Program
    {
        public static void Main()
        {

            Program p = new Program();
            p.CreatingThreadsToToRunCalculations();

            Console.WriteLine("Press any key to quit...");
            Console.ReadKey();
        }

        public void CreatingThreadsToToRunCalculations()
        {
            Thread t1 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^1: {0}", CalculatePower(10, 1));
            });
            Thread t2 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^2: {0}", CalculatePower(10, 2));
            });
            Thread t3 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^3: {0}", CalculatePower(10, 3));
            });
            Thread t4 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^4: {0}", CalculatePower(10, 4));
            });

            t1.Start();
            t2.Start();
            t3.Start();
            t4.Start();

            ThreadExtensions.JoinAll(t1, t2, t3, t4);
            
            // The above is equivalent to
            // t1.Join();
            // t2.Join();
            // t3.Join();
            // t4.Join();

        }

        private int CalculatePower(int a, int power)
        {
            if (power == 1) return 10;
            int value = 10;

            for (var i = 1; i < power; i++)
            {
                value *= 10;
            }
            return value;
        }
    }
}

Blair

Threads To Schedule Work

November 22, 2010 Leave a comment
using System;
using System.Linq;
using System.Runtime.Remoting.Contexts;
using System.Threading;

namespace ThreadsAreForScheduling
{
    class Program
    {
        public static void Main()
        {

            Program p = new Program();
            p.CreatingThreadsToToRunCalculations();

            Console.WriteLine("Press any key to quit...");
            Console.ReadKey();
        }

        public void CreatingThreadsToToRunCalculations()
        {
            Thread t1 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^1: {0}", CalculatePower(10, 1));
            });
            Thread t2 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^2: {0}", CalculatePower(10, 2));
            });
            Thread t3 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^3: {0}", CalculatePower(10, 3));
            });
            Thread t4 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^4: {0}", CalculatePower(10, 4));
            });

            t1.Start();
            t2.Start();
            t3.Start();
            t4.Start();

        }

        
        private int CalculatePower(int a, int power)
        {

            if (power == 1) return 10;

            int value = 10;

            for (var i = 1; i < power; i++)
            {
                value *= 10;
            }

            return value;
        }
    }
}

Note this is not recommended. You should use Tasks or the ThreadPool as threads are a means of scheduling and are expensive.

Blair…

Windows Forms and TPL with BlockingCollections

November 18, 2010 Leave a comment

Just Love Task Parallel Library
Link

Blair..

Parallel Loops and Exiting Early

November 18, 2010 Leave a comment

Quick demo on how to exit early from a parallel loop. You can use either break nor stop. Stop terminate loops as early as possible while break lets early scheduled loops complete till completion.

using System;
using System.Threading.Tasks;

namespace ParallelLoops
{
    class Program
    {
        public static void Main()
        {
            Program program = new Program();
            program.ExitingLoopsPrematurely();

            Console.WriteLine("Press any key to quit...");
            Console.ReadKey();
        }

        public void ExitingLoopsPrematurely()
        {
            var result = Parallel.For(1, 100, (value, state) =>
                                     {
                                         if (value % 20 == 0)
                                             state.Break();

                                         Console.WriteLine("Value: {0}", value);

                                     });

            Console.WriteLine("Completed {0}, Exited at Iteration: {1}", result.IsCompleted, result.LowestBreakIteration );
        }
    }
}

Handling Causality with APM and Not ThreadPool QueueUserWorkItem

November 17, 2010 Leave a comment
using System;
using System.Runtime.Remoting.Messaging;

namespace AsynchronousProgrammingModelSamples
{

    public class ApmAsychExecution
    {
        public void ExecuteAsynchronouslyWithCallback<TResult>(Func<TResult> function, Action<TResult> callback,
                                                              Action<Exception> exception)
        {
            TResult result = default(TResult);

            Action action = () =>
                                {
                                    result = function();
                                };

            action.BeginInvoke(fn =>
                                  {

                                      try
                                      {
                                          AsyncResult aresult = (AsyncResult) fn;
                                          Action caller = (Action) aresult.AsyncDelegate;
                                          caller.EndInvoke(aresult);
                                          callback(result);
                                      }catch(Exception e)
                                      {
                                          exception(e);
                                      }
                                  }, null);

        }

        public void ExecuteAsynchronouslyWithCallback<TArg, TResult>(Func<TArg,TResult> function, Action<TResult> callback,
                                                              Action<Exception> exception, TArg argument)
        {
            TResult result = default(TResult);

            Action action = () =>
            {
                result = function(argument);
            };

            action.BeginInvoke(fn =>
            {

                try
                {
                    AsyncResult aresult = (AsyncResult)fn;
                    Action caller = (Action)aresult.AsyncDelegate;
                    caller.EndInvoke(aresult);
                    callback(result);
                }
                catch (Exception e)
                {
                    exception(e);
                }
            }, null);

        }
    }

    public class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public override string ToString()
        {
            return String.Format("Id: {0}, Name: {1}", Id, Name);
        }
    }

    public class Program
    {
        public static void Main()
        {
            Program p = new Program();
            p.ExecuteItemAsyncronously();

            Console.WriteLine("Press any key to quit..");
            Console.ReadKey();
        }

        public void ExecuteItemAsyncronously()
        {
            ApmAsychExecution apm = new ApmAsychExecution();
            apm.ExecuteAsynchronouslyWithCallback(
                    () => new Customer { Id = 1, Name = "Blair Davidson" }, Console.WriteLine, Console.WriteLine
                );
            apm.ExecuteAsynchronouslyWithCallback(
                    name => new Customer { Id = 1, Name = name }, Console.WriteLine, Console.WriteLine, "Patrick Smith"
                );
            apm.ExecuteAsynchronouslyWithCallback(
                    () =>
                        {
                            throw new InvalidOperationException("Error Testing....");
                            return new Customer {Id = 1, Name = "Blair Davidson"};
                        }, Console.WriteLine, Console.WriteLine
                );
        }
    }
}

APM Techniques with FileStream

November 17, 2010 Leave a comment
using System;
using System.IO;
using System.Linq;
using System.Text;

namespace AsynchronousProgrammingModelSamples
{
    public class Program
    {
        private string path = @"C:\test.txt";

        static void Main()
        {
            Program p = new Program();
            p.WriteContentsToFile();
           // p.ProcessLinesWithAPMUsingBlockWait();
           // p.ProcessLinesWithAPMUsingPolling();
            p.ProcessLinesWithAPMUsingCallbacks();
            Console.WriteLine("Press any key to quit..");
            Console.ReadKey();
        }

        public void ProcessLinesWithAPMUsingCallbacks()
        {
            FileStream stream = null;
            byte[] data = null;
            try
            {
                stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous);
                data = new byte[stream.Length];
                stream.BeginRead(data, 0, data.Length, x =>
                                                           {
                                                               Console.WriteLine(Encoding.ASCII.GetString(data));
                                                           }, null);
            }
            catch (Exception e)
            {

            }
            finally
            {
                if (stream != null) stream.Close();
            }
        }

        public void ProcessLinesWithAPMUsingPolling()
        {
            FileStream stream = null;
            byte[] data = null;
            try
            {
                stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous);
                data = new byte[stream.Length];
                IAsyncResult result = stream.BeginRead(data, 0, data.Length, null, null);

                while(!result.IsCompleted) // Pool and do something - Not a great way to do things 🙂
                {
                    Console.WriteLine("Waiting ....");
                }


                stream.EndRead(result);

                Console.WriteLine(Encoding.ASCII.GetString(data));

            }
            catch (Exception e)
            {

            }
            finally
            {
                if (stream != null) stream.Close();
            }
        }

        public void ProcessLinesWithAPMUsingBlockWait()
        {
            FileStream stream = null;
            byte[] data = null;
            try
            {
                stream = new FileStream(path,FileMode.Open,FileAccess.Read,FileShare.Read,1024,FileOptions.Asynchronous);
                data = new byte[stream.Length];
                IAsyncResult result = stream.BeginRead(data, 0, data.Length, null, null);

                stream.EndRead(result); // Basically we are blocking here util finished so no difference to the synch
                                        // version

                Console.WriteLine(Encoding.ASCII.GetString(data));

            }
            catch (Exception e)
            {

            }
            finally
            {
                if(stream != null) stream.Close();
            }
        }

        public void WriteContentsToFile()
        {
            var items = Enumerable.Range(1, 1000)
                                  .Select(x => x.ToString())
                                  .ToArray();

            var text = String.Join(Environment.NewLine, items);
            File.WriteAllText(path, text);

        }
    }
}

Blair…

APM and TPL – Reading Files

November 16, 2010 Leave a comment
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace APMExamples
{
    class Program
    {
        static void Main()
        {
            Program p = new Program();
            p.ReadFileContentsAsyncAndUseAContinuationToPrintResults();

            Console.WriteLine("Press any key to quit..");
            Console.ReadKey();

        }

        public void ReadFileContentsAsyncAndUseAContinuationToPrintResults()
        {
            var stream = new FileStream(@"C:\Projects\TPLSamples\TPLSamples.sln", FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 8 * 1024, FileOptions.Asynchronous);
            byte[] data = new byte[stream.Length];

            var t = Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead, data, 0, data.Length, null);
            t.ContinueWith(x =>
                               {
                                   Console.WriteLine(Encoding.ASCII.GetString(data));
                                   stream.Close();
                               });
        }
    }
}