Search code examples
c#parallel-processing.net-4.0task-parallel-libraryparallel.invoke

When is Parallel.Invoke useful?


I'm just diving into learning about the Parallel class in the 4.0 Framework and am trying to understand when it would be useful. At first after reviewing some of the documentation I tried to execute two loops, one using Parallel.Invoke and one sequentially like so:

static void Main()
{
    DateTime start = DateTime.Now;
    Parallel.Invoke(BasicAction, BasicAction2);
    DateTime end = DateTime.Now;
    var parallel = end.Subtract(start).TotalSeconds;
    
    start = DateTime.Now;
    BasicAction();
    BasicAction2();
    end = DateTime.Now;
    var sequential = end.Subtract(start).TotalSeconds;
    
    Console.WriteLine("Parallel:{0}", parallel.ToString());
    Console.WriteLine("Sequential:{0}", sequential.ToString());
    Console.Read();
}
static void BasicAction()
{
    for (int i = 0; i < 10000; i++)
    {
        Console.WriteLine("Method=BasicAction, Thread={0}, i={1}", Thread.CurrentThread.ManagedThreadId, i.ToString());
    }
}

static void BasicAction2()
{
    for (int i = 0; i < 10000; i++)
    {
       Console.WriteLine("Method=BasicAction2, Thread={0}, i={1}", Thread.CurrentThread.ManagedThreadId, i.ToString());
    }
}

There is no noticeable difference in time of execution here, or am I missing the point? Is it more useful for asynchronous invocations of web services or...?

EDIT: I removed the DateTime with Stopwatch, removed the write to the console with a simple addition operation.

UPDATE - Big Time Difference Now: Thanks for clearing up the problems I had when I involved Console

static void Main()
{
    Stopwatch s = new Stopwatch();
    s.Start();
    Parallel.Invoke(BasicAction, BasicAction2);
    s.Stop();
    var parallel = s.ElapsedMilliseconds;

    s.Reset();
    s.Start();
    BasicAction();
    BasicAction2();
    s.Stop();

    var sequential = s.ElapsedMilliseconds;
    
    Console.WriteLine("Parallel:{0}", parallel.ToString());
    Console.WriteLine("Sequential:{0}", sequential.ToString());
    Console.Read();
}

static void BasicAction()
{
    Thread.Sleep(100);

}

static void BasicAction2()
{
    Thread.Sleep(100);
}

Solution

  • The test you are doing is nonsensical; you are testing to see if something that you can not perform in parallel is faster if you perform it in parallel.

    Console.Writeline handles synchronization for you so it will always act as though it is running on a single thread.

    From here:

    ...call the SetIn, SetOut, or SetError method, respectively. I/O operations using these streams are synchronized, which means multiple threads can read from, or write to, the streams.

    Any advantage that the parallel version gains from running on multiple threads is lost through the marshaling done by the console. In fact I wouldn't be surprised to see that all the thread switching actually means that the parallel run would be slower.

    Try doing something else in the actions (a simple Thread.Sleep would do) that can be processed by multiple threads concurrently and you should see a large difference in the run times. Large enough that the inaccuracy of using DateTime as your timing mechanism will not matter too much.