Partager via


Parallel Programming in .NET Framework 4: Getting Started

With this post I want to start a series devoted to the new parallel programming features in .NET Framework 4 and introduce you the Task Parallel Library (TPL).

Update. The list of posts in this series:

I have to admit that I’m not an expert in multithreading or parallel computing. However, people often ask me about easy introductions and beginner’s samples for new features. And I have an enormous advantage over most newbies in this area – I can ask people who developed this library about what I’m doing wrong and what to do next. By the way, if you want to ask someone about what to do next with your parallel program, I'd recommend you to go to this forum - Parallel Extensions to the .NET Framework Forum.

I have a simple goal this time. I want to parallelize a long-running console application and add a responsive WPF UI. By the way, I’m not going to concentrate too much on measuring performance. I’ll try to show the most common caveats, but in most cases just seeing that the application runs faster is good enough for me.

Now, let the journey begin. Here’s my small program that I want to parallelize. The SumRootN method returns the sum of the nth root of all integers from one to 10 million, where n is a parameter. In the Main method, I call this method for roots from 2 through 19. I’m using the Stopwatch class to check how many milliseconds the program takes to run.

using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using System;

class Program
{

    static void Main(string[] args)
    {
        var watch = Stopwatch.StartNew();
        for (int i = 2; i < 20; i++)
        {
            var result = SumRootN(i);
            Console.WriteLine("root {0} : {1} ", i, result);
        }
        Console.WriteLine(watch.ElapsedMilliseconds);
        Console.ReadLine();
    }

    public static double SumRootN(int root)
    {
        double result = 0;
        for (int i = 1; i < 10000000; i++)
        {
            result += Math.Exp(Math.Log(i) / root);
        }
        return result;
    }
}

On my 3-GHz dual-core 64-bit computer with 4 GB of RAM the program takes about 18 seconds to run.

Since I’m using a for loop, the Parallel.For method is the easiest way to add parallelism. All I need to do is replace

for (int i = 2; i < 20; i++)
{
    var result = SumRootN(i);
    Console.WriteLine("root {0} : {1} ", i, result);
}

with the following parallel code:

Parallel.For(2, 20, (i) =>
{
    var result = SumRootN(i);
    Console.WriteLine("root {0} : {1} ", i, result);
});

Notice how little the code changed. I supplied start and end indices (same as I did in the simple loop) and a delegate in the form of a lambda expression. I didn’t have to change anything else, and now my little program takes about 9 seconds.

When you use the Parallel.For method, the .NET Framework automatically manages the threads that service the loop, so you don’t need to do this yourself. But remember that running code in parallel on two processors does not guarantee that the code will run exactly twice as fast. Nothing comes for free; although you don’t need to manage threads yourself, the .NET Framework still uses them behind the scenes. And of course this leads to some overhead. In fact, if your operation is simple and fast and you run a lot of short parallel cycles, you may get much less benefit from parallelization than you might expect.

Another thing you probably noticed when you run the code is that now you don’t see the results in the proper order: Instead of seeing increasing roots, you see quite a different picture. But let’s pretend that we just need results, without any specific order. In this blog post, I’m going to leave this problem unresolved.

Now it’s time to take things one step further. I don’t want to write a console application; I want some UI. So I’m switching to Windows Presentation Foundation (WPF). I have created a small window that has only one Start button, one text block to display results, and one label to show elapsed time.

The event handler for the sequential execution looks pretty simple:

private void start_Click(object sender, RoutedEventArgs e)
{
    textBlock1.Text = "";
    label1.Content = "Milliseconds: ";

    var watch = Stopwatch.StartNew();
    for (int i = 2; i < 20; i++)
    {
        var result = SumRootN(i);
        textBlock1.Text += "root " + i.ToString() + " " +
                           result.ToString() + Environment.NewLine;

    }
    var time = watch.ElapsedMilliseconds;
    label1.Content += time.ToString();
}

 

Compile and run the application to make sure that everything works fine. As you might notice, UI is frozen and the text block does not update until all of the computations are done. This is a good demonstration of why WPF recommends never executing long-running operations in the UI thread.

Let’s change the for loop to the parallel one:

Parallel.For(2, 20, (i) =>
{
    var result = SumRootN(i);
    textBlock1.Text += "root " + i.ToString() + " " +
                        result.ToString() + Environment.NewLine;

});

Click the button…and…get an InvalidOperationException that says “The calling thread cannot access this object because a different thread owns it.”

What happened? Well, as I mentioned earlier, the Task Parallel Library still uses threads. When you call the Parallel.For method, the .NET Framework starts new threads automatically. I didn’t have problems with the console application because the Console class is thread safe. But in WPF, UI components can be safely accessed only by a dedicated UI thread. Since Parallel.For uses worker threads besides the UI thread, it’s unsafe to manipulate the text block directly in the parallel loop body. If you use, let’s say, Windows Forms, you might have different problems, but problems nonetheless (another exception or even an application crash).

Luckily, WPF provides an API that solves this problem. Most controls have a special Dispatcher object that enables other threads to interact with the UI thread by sending asynchronous messages to it. So our parallel loop should actually look like this:

Parallel.For(2, 20, (i) =>
{
    var result = SumRootN(i);
    this.Dispatcher.BeginInvoke(new Action(() =>
        textBlock1.Text += "root " + i.ToString() + " " +
                           result.ToString() + Environment.NewLine)
         , null);
});

In the above code, I’m using the Dispatcher to send a delegate to the UI thread. The delegate will be executed when the UI thread is idle. If UI is busy doing something else, the delegate will be put into a queue. But remember that this type of interaction with the UI thread may slow down your application.

Now I have our parallel WPF application running on my computer almost twice fast. But what about this freezing UI? Don’t all modern applications have responsive UI? And if Parallel.For starts new threads, why is the UI thread still blocked?

The reason is that Parallel.For tries to exactly imitate the behavior of the normal for loop, so it blocks the further code execution until it finishes all its work.

Let’s take a short pause here. If you already have an application that works and satisfies all your requirements, and you want to simply speed it up by using parallel processing, it might be enough just to replace some of the loops with Parallel.For or Parallel.ForEach. But in many cases you need more advanced tools.

To make the UI responsive, I am going to use tasks, which is a new concept introduced by the Task Parallel Library. A task represents an asynchronous operation that is often run on a separate thread. The .NET Framework optimizes load balancing and also provides a nice API for managing tasks and making asynchronous calls between them. To start an asynchronous operation, I’ll use the Task.Factory.StartNew method.

So I’ll delete the Parallel.For and replace it with the following code, once again trying to change as little as possible.

for (int i = 2; i < 20; i++)
{
    var t = Task.Factory.StartNew(() =>
    {
        var result = SumRootN(i);
        this.Dispatcher.BeginInvoke(new Action(() =>
            textBlock1.Text += "root " + i.ToString() + " " +
               result.ToString() + Environment.NewLine)
            ,null);

    });
}

 

Compile, run… Well, UI is responsive. I can move and resize the window while the program calculates the results. But I have two problems now:

1. My program tells me that it took 0 milliseconds to execute.

2. The program calculates the method only for root 20 and shows me a list of identical results.

Let’s start with the last one. C# experts can shout it out: closure! Yes, i is used in a loop, so when a thread starts working, i’s value has already changed. Since i is equal to 20 when the loop is exited, this is the value that is always passed to newly created tasks.

Problems with closure like this one are common when you deal with lots of delegates in the form of lambda expressions (which is almost inevitable with asynchronous programming), so watch out for it. The solution is really easy. Just copy the value of the loop variable into a variable declared within the loop. Then use this local variable instead of the loop variable.

for (int i = 2; i < 20; i++)
{
    int j = i;
    var t = Task.Factory.StartNew(() =>
    {
        var result = SumRootN(j);
        this.Dispatcher.BeginInvoke(new Action(() =>
             textBlock1.Text += "root " + j.ToString() + " " +
                                 result.ToString() + Environment.NewLine)
             , null);
    });
}

Now let’s move to the second problem: The execution time isn’t measured. I perform the tasks asynchronously, so nothing blocks the code execution. The program starts the tasks and goes to the next line, which is reading time and displaying it. And it doesn’t take that long, so I get 0 on my timer.

Sometimes it’s OK to move on without waiting for the threads to finish their jobs. But sometimes you need to get a signal that the work is done, because it affects your workflow. A timer is a good example of the second scenario.

To get my time measurement, I have to wrap code that reads the timer value into yet another method from the Task Parallel Library: TaskFactory.ContinueWhenAll. It does exactly what I need: It waits for all the threads in an array to finish and then executes the delegate. This method works on arrays only, so I need to store all the tasks somewhere to be able to wait for them all to finish.

Here’s what my final code looks like:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
    public static double SumRootN(int root)
    {
        double result = 0;
        for (int i = 1; i < 10000000; i++)
        {
            result += Math.Exp(Math.Log(i) / root);
        }
        return result;
    }

    private void start_Click(object sender, RoutedEventArgs e)
    {
        textBlock1.Text = "";
        label1.Content = "Milliseconds: ";

        var watch = Stopwatch.StartNew();
        List<Task> tasks = new List<Task>();
        for (int i = 2; i < 20; i++)
        {
            int j = i;
            var t = Task.Factory.StartNew(() =>
            {
                var result = SumRootN(j);
                this.Dispatcher.BeginInvoke(new Action(() =>
                     textBlock1.Text += "root " + j.ToString() + " " +
                                         result.ToString() +
                                         Environment.NewLine)
                , null);
            });
            tasks.Add(t);
        }

        Task.Factory.ContinueWhenAll(tasks.ToArray(),
              result =>
              {
                  var time = watch.ElapsedMilliseconds;
                  this.Dispatcher.BeginInvoke(new Action(() =>
                      label1.Content += time.ToString()));
              });

    }
}

Finally, everything works as expected: I have a list of results, the UI does not freeze, and the elapsed time displays correctly. The code definitely looks quite different from what I started with, but surprisingly it’s not that long, and I was able to reuse most of it (thanks to lambda expression syntax).

Again, I tried to cover common problems that most beginners in parallel programming and multithreading are likely to encounter, without getting too deep into details. But I expect this to be just the first post in a series. But if you don’t want to wait for my next posts, check out Parallel Programming in .NET Framework on MSDN and the parallel framework team blog.

Of course, as with any other post I publish on this blog, I hope that it’s useful for you. But this one is a little bit different from the pure C# posts that I’ve written before. So, here’s a question: How useful is this type of beginner’s content to you? Do you want to see more of it? And if you’re thinking about using parallel and asynchronous programming now, what kind of scenario do you have in mind? I really need your feedback, and I’m looking forward to your comments.

P.S.

Thanks to everybody who helped me this time: Dmitry Lomov and Michael Blome for getting me started with TPL, Danny Shih and Mads Torgersen for reviewing this and providing comments, Mick Alberts and Robin Reynolds-Haertle for editing.

Comments

  • Anonymous
    June 01, 2010
    Hi Alexandra Yes, please keep posting this type of beginner's content. It's very useful. I don't know yet how I will use it in our projects, but it's anyway good knowledge! Thanks

  • Anonymous
    June 01, 2010
    Hi Alexandra, I thought your posting was very easy to understand and very helpful to me. Please keep up with this series. Especially the tips for keeping the UI responsive are very interesting to me, as we use regular threads in our WPF application a lot and this series will help us to eventually substitute the manual thread management by the Taks library. Thank You

  • Anonymous
    June 01, 2010
    very nice, I'd like to see more articles that are easy to follow (like this one). Other series might mention other useful functions, caveats, typical scenarios when TPL can be used (databases, asp.net)? thanks

  • Anonymous
    June 01, 2010
    thank you very much for new article and a important one also.

  • Anonymous
    June 02, 2010
    Great read!!

  • Anonymous
    June 02, 2010
    Hi, thanks for such a nice article, i'ld like to learn a new one...thanks again

  • Anonymous
    June 02, 2010
    Very nice article...pls continue to post such articles.

  • Anonymous
    June 02, 2010
    Good article - makes what appears to be a difficult concept much easier to understand and follow. Keep up the good work.

  • Anonymous
    June 02, 2010
    Very good, thought provoking stuff. I hadn't had much of a change to look at the Parallel Programming features in .NET 4 before.  This introduction was easy to follow and understand.  It also immediately shows some of the performance benefits that can be gleaned from a relatively small coding investment which is always a real win-win situation.  Keep it up!

  • Anonymous
    June 02, 2010
    Excelent! Pretty clear! I've created a training site (www.ittraining.com.ar) in Spanish and I'm going to post about Parallel Programming soon. Your article is going to be referenced from my post for sure. Thanks! I'm from Argentina by the way.

  • Anonymous
    June 03, 2010
    Nice article. I'd been looking around for an understandable place to start on parallel programming and this is at exactly the right level for me. Do continue with the series. :-)

  • Anonymous
    June 03, 2010
    I like the "baby steps" approach when getting exposed to something new.  This is helpful stuff.   One thing that would be useful in a Part 2 of this would be how to put some sort of throttle on the resources.  I worry about unexpected parameter values or other things those pesky users might do to mess up a perfectly good routine.  Is there a way to gracefully "cancel" something that is turning into a parallelized runaway?  Do we have to somehow leave at least one core alone to even be able to catch a cancel request?  

  • Anonymous
    June 03, 2010
    Thanks to everybody for feedback. I'm really happy to read this. Beginners' topics like this one are quite hard to write and I'm glad that it turned out to be interesting and useful. @KD TPL has more advanced features, of course. For example, you can cancel the parallel for loop: msdn.microsoft.com/.../ee256691.aspx You can also handle exceptions: msdn.microsoft.com/.../dd460695.aspx

  • Anonymous
    June 03, 2010
    This is much more helpful than the stuff on MSDN.  Showing progression in change is the best way to explain new features!  Thanks!

  • Anonymous
    June 03, 2010
    Great article!  Very useful.  I do have a question.  I increased the iterations to 50000 and the CPU useage was about 99% for a hour or so.  This made it almost impossible to use any other applications that was running.  Is there a way to limit the total CPU useage to lets say 80%????

  • Anonymous
    June 04, 2010
    Thanks for the post of course. But I just can't help to comment on how ugly it is to write code for parallels wow. I know why you guys did it that way but Microsoft should have spent the time in making it the proper more user friendly way... Could have started by using regular c# syntax by doing away with all the silly parameters to the parallel for function. Syntax should have just been changed to the following for the for pfor(int i = 0; i < 20; i++) { // do stuff here } p stands for parallel ofcourse.. It just starts getting really ugly when you start doing things like this... Parallel.For(2, 20, (i) => { /* do something here */ }); what is 2? what is 20? why is i encapsulated in ()? whats equal or greater than... don't answer that because I already know the answers... just its not as simple and basic as a regular for loop, and I think it should be simple and basic to promote its use and make it easier to read.

  • Anonymous
    June 04, 2010
    I really enjoyed reading this post. I can definitely follow it and think of ways I can use it in actual projects. Keep it up.

  • Anonymous
    June 05, 2010
    The comment has been removed

  • Anonymous
    June 06, 2010
    Great Article and very useful. I have the below scenario can you please suggest how parallelism can be achieved for this. I have a windows service running on .Net 2.0 and what it does is fetches the Group ID from DB and fetches list of reports for each group from DB and fetches each of the report data from DB and writesthe report data of various reports into different tabs of a Excel report. Right now executing the different reports like getting the report data for each task, and writing it as a tab into the excel workbook is done synchronously. I think we can really get parallelism in this scenario. Can you please advise or illustrate such kind of scenario through one of your articles or reference one, so that with out causing any lock on the excel file and running out of memory , how can we achieve writing different reports into same excel workbook in a parellel way. Very much thanks in advance.

  • Anonymous
    June 06, 2010
    A great article. Very good for beginners. Please continue with more such posts. Thanks!!

  • Anonymous
    June 06, 2010
    very nice

  • Anonymous
    June 07, 2010
    I am a working application programmer and find this kind of article extremely useful in quickly overviewing a technology. I am writing an application that extracts data from what might be many text files. I thought parallel processing would help but I had on my 'nice to have - later' list. Now I will be looking to use it my next major version which is in the design stage right now.

  • Anonymous
    June 07, 2010
    The comment has been removed

  • Anonymous
    June 07, 2010
    Omg, can't wait to use Parallel.ForEach loops :)

  • Anonymous
    June 08, 2010
    Thanks Alexandra for the great post.  Thanks all for your comments.  I'll attempt to answer a few questions here. Dave, There's no way to throttle CPU utilization directly (at least not using our APIs).  However, you can probably achieve what you want by setting the maximum degree of parallelism via a ParallelOptions object.  For example,    ParallelOptions ops = new ParallelOptions() { MaxDegreeOfParallelism = 2 };    Parallel.For(2, 20, ops, (i) => { }); This will cause the loop to never have more than 2 concurrent operations at any given time, which should indirectly affect CPU utilization (assuming you're on a machine with more than two cores). xer, Yes, things would have looked nicer if we added language features (like a new "pfor" keyword to C#) to support parallelism.  However, the advantage to only using libraries if that all of this new parallel programming support is accessible from any .NET language.  Alexandra stuck with C# in this post, but she could have used VB, F#, C++/CLI, etc. just as easily. Lastly, let me point everyone to the PFx Forum:    social.msdn.microsoft.com/.../threads This is the best place to ask questions or post feedback regarding the new parallel programming support in .NET 4. Danny

  • Anonymous
    June 09, 2010
    Great artiicle! My first thought is that the TPL will replace the BackgroundWorker, so I agree with KD that cancellation and progress messages would be excellent topics for future blog posts.

  • Anonymous
    June 09, 2010
    Good Article, yes please keep going with this stuff for the beginners.

  • Anonymous
    June 11, 2010
    Really nice article, looking for more on this..

  • Anonymous
    June 12, 2010
    Great post! I am new with Parallel Programming. But I want to ask people a questions: How do we set up a parallel system to test our applications as well as samples?

  • Anonymous
    June 12, 2010
    you were an eye opener, u just made a realize a lot of potential improvements at my client project

  • Anonymous
    June 13, 2010
    Very useful post. I am currently designing an app for simulation purposes. The vision of the app is that it should be able to process around 24 GB of data (lots of sequential and nested loops, millions of records and some recursive procedures too) every hour. I have been looking for a parallel solution in C# and I hope to see more posts from you soon. Especially the use of For Each parallel loop and more in depth look at the tasks library. Thanks a lot!

  • Anonymous
    June 13, 2010
    I had translate this article to chinese. 我已将此文章翻译成中文: www.cnblogs.com/.../parallel-programming-in-net-framework-4-getting-started.html

  • Anonymous
    June 13, 2010
    The comment has been removed

  • Anonymous
    June 15, 2010
    @Rob I think you misunderstood the idea. I'm using WPF Dispatcher not to speed up the work, but to communicate with the UI thread. All computations are done in the background thread and this is where parallelization is happening. The Dispatcher only helps me to show results that are produced by different tasks. @tianfan Thanks for translation.

  • Anonymous
    June 16, 2010
    nice job! keep going on.

  • Anonymous
    June 20, 2010
    Sensational just sensational blog... Keep Rocking Alexandra Rusina

  • Anonymous
    June 21, 2010
    What about this syntax? new Action(() => {    var watch = Stopwatch.StartNew();    ParallelEnumerable.Range(2, 18).AsOrdered().ForAll((i) =>    {        this.Dispatcher.BeginInvoke(() => textBlock1.Text += "root " +                        i.ToString() + " " +                        SumRootN(i).ToString() +                        Environment.NewLine);    });    this.Dispatcher.BeginInvoke(() => label1.Content += watch.ElapsedMilliseconds.ToString()); }).BeginInvoke(); I wish that Microsoft implemented "yield return" inside anonimous functions, then you could create any crazy sequences inline like this: new Action(() => {    var watch = Stopwatch.StartNew();    IEnumerable<int> sequence = () =>    {        for (int i = 2; i < 20; i++) yield return i;    };    sequence.AsParallel().AsOrdered().ForAll((i) =>    {        this.Dispatcher.BeginInvoke(() => textBlock1.Text += "root " +                        i.ToString() + " " +                        SumRootN(i).ToString() +                        Environment.NewLine);    });    this.Dispatcher.BeginInvoke(() => label1.Content += watch.ElapsedMilliseconds.ToString()); }).BeginInvoke();

  • Anonymous
    June 21, 2010
    @Michael I can only repeat that I'm not an expert in this area.... This is just a beginners' intro on what's available right now. All I can say is that the syntax you are talking about is not available in the .NET 4. If you want to suggest your ideas and discuss them with the people that develop this library here are some links you can try: blogs.msdn.com/.../pfxteam - This blog is supported by the team that developed TPL and you can get answers from people that designed and developed this library. social.msdn.microsoft.com/.../threads - this is TPL forum. Here you can discuss your ideas with MVPs and other members of the community connect.microsoft.com/VisualStudio - you can file you suggestions at Microsoft Connect for Visual Studio. The community can comment and vote on your suggestion and Microsoft employees look through the connect bugs and provide answers and comments.

  • Anonymous
    June 21, 2010
    Actually, the first syntax should compile and work exactly like your example. Take a look at ParallelEnumerable, AsParallel(), and ForAll(), those give you an alternative to Parallel class. Second syntax is my wish, so I will use your suggestion and go to blogs that you gave me. Thanks.

  • Anonymous
    June 21, 2010
    @Michael Oh, I see now. Well, I'm actually getting rid of all the "BeginInvoke" calls in my next post: blogs.msdn.com/.../parallel-programming-task-schedulers-and-synchronization-context.aspx The "BeginInvoke" is a common pattern, but in most cases TPL has its own way of doing things and other patterns are more appropriate.

  • Anonymous
    June 21, 2010
    The comment has been removed

  • Anonymous
    June 24, 2010
    The comment has been removed

  • Anonymous
    June 24, 2010
    Good article for beginners

  • Anonymous
    June 25, 2010
    The comment has been removed

  • Anonymous
    June 30, 2010
    Excellent article.  Pls keep up posting such beginner articles despite the critics comes along from some unbalanced ones.  Thanks.

  • Anonymous
    June 30, 2010
    Hey man ! This post hepls me a lots ! Thank you  very much!

  • Anonymous
    July 05, 2010
    This is a very helpfull article for those switching to framework 4.0. Describes the concept in a nice sequential way and keeps the reader with it.

  • Anonymous
    July 06, 2010
    Alex, When I used this.Dispatcher.BeginInvoke, it works, however, if I use Dispatcher.CurrentDispatcher.BeginInvoke , it does not work. Can you tell me the reason why ? Also, in Win Form app (not WPF), I dont have "this.Dispatcher", so how do I go about in Win Form ? Thanks. ScreenStarer

  • Anonymous
    July 22, 2010
    Hi Alexandra, Thank you for a good and easy to understand article. I'm looking forward to read more posts like this. Regards, Evgeny Bogolyubov.

  • Anonymous
    July 26, 2010
    This article is great. Very easy to understand. Please keep it up.

  • Anonymous
    August 01, 2010
    Wouldn’t it be better to add support for parallelism to the C# language instead of the .Net library?

  • Anonymous
    August 02, 2010
    @ Screen Starer Take a look at the next post in the series: blogs.msdn.com/.../parallel-programming-task-schedulers-and-synchronization-context.aspx It talks about Win Form and alternatives to the dispatcher pattern.

  • Anonymous
    August 02, 2010
    @ Max This library is not just for C#. You can use it from C++, Visual Basic, and F#. Also, this is actually V 1.0. It's interesting to see how many people will use it, what use cases will be the most common, etc. before making changes in the language.

  • Anonymous
    August 04, 2010
    Thanks, Alexandra.  I thought this article was excellent. It has just the right level and amount information for a first introduction to Tasks.  Basic introductions like this are great to help developers get over any initial hesitance when reviewing a new code library.

  • Anonymous
    August 10, 2010
    Hi Alexandra, This article is very simple to read and understand. In fact I just started to learn what's new in C# and came across this article. I don't have any patience to read tech articles, in the middle I used to divert to something else. But, surprisingly I had read this one completely :). Thanks for explaining this in it's simplest way. Keep posting such articles. Regards Daniel

  • Anonymous
    August 10, 2010
    This is a simple and informative article which you have posted. Good one for getting a feeler of Parallel Programming and TPL

  • Anonymous
    August 11, 2010
    Yes, this is a GREAT article, keep them coming! Still don't like lambda though, my brain does not work that way :-). On that point, does one have to use lambda expressions or can the code be written another way (even if its more verbose?).

  • Anonymous
    August 11, 2010
    @VinceJS You can always use delegates: create a method and then instantiate a delegate with it.

  • Anonymous
    September 10, 2010
    The comment has been removed

  • Anonymous
    September 13, 2010
    great tutorial for me as beginner....

  • Anonymous
    September 21, 2010
    great get started article!!

  • Anonymous
    September 28, 2010
    Excellent. This article is exactly what I needed and perfect for someone wanting to get start with parallel programming. Thanks

  • Anonymous
    October 29, 2010
    Help!  need VB.NET sourcecode of this article. Please publish.

  • Anonymous
    December 02, 2010
    What's the point of a gazzilon "Great article" comments?

  • Anonymous
    December 18, 2010
    This is really a great article to start with. You have explained in a very simple terms. You are a prefect teacher. Thanks for the Post.

  • Anonymous
    December 20, 2010
    Good article... I also heared about some new keywords are comming in .Net 5.0 like await, async which does parallel programming even simpler If you could put some light on this then it woul be great Thanks, Sandesh Daddi www.sanshark.com

  • Anonymous
    December 21, 2010
    @Sandesh Here it is: blogs.msdn.com/.../async.aspx

  • Anonymous
    February 07, 2011
    The joy of learning doubles up for me when i get to read such articles. Thanks a lot Alexandra !!

  • Anonymous
    April 04, 2011
    Oh I really  like the post ,but I have a different and better solution here. The  .NET Framework 4 includes extended support for writing parallel applications, through enhancements to the CLR itself as well as through new libraries commonly referred to as 'Parallel Extensions to the .NET Framework.. Our team provides all type of web application development ranging from large web applications, real estate websites, classified listing and all categories using Microsoft ASP.Net, PHP, ASP, .NET Framework 4 programming, Visual Studio 2010 programming, C#. We also have expertise in wordpress theme customizations using premium and paid themes as well as free themes. We are efficient  in websites design and development  using   Wordpress also. We have very good SEO team and social media managers who can take on your internet marketing assignments.

  • Anonymous
    May 25, 2011
    Quite interesting and a very good post for the novice

  • Anonymous
    October 02, 2011
    Hey this was definitely awesome tutorial. Now i want to ask you this abouth this tutorial. You used at the last code this        Task.Factory.ContinueWhenAll(tasks.ToArray(),               result => Why there is "result =>"   what does this mean ? what does this do ? thank you.

  • Anonymous
    February 19, 2012
    Thanks for the intro to parallel programming! This is just the sort of gentle introduction to th topic that I was looking for. I just wanted to say that instead of making the first loop in your example parallel, I thought it made much more sense to make the second one so. (After all, the real work was being done in the second loop anyway & the order didn't really matter)... in other words, I replaced the following        for (int i = 1; i < 10000000; i++)         {             result += Math.Exp(Math.Log(i) / root);         } with            Parallel.For(1, 10000000, (i) =>                {                    result += Math.Exp(Math.Log(i) / root);                }); Not only did I gain the speed up from the parallelization, but I didn't have to worry about the output order getting all scrambled up, like it was in your example. Todd

  • Anonymous
    June 17, 2012
    Hi Alexandra, Thanks you so much for providing such a great article... I've been looking around for quite a while trying to understand Task and why they were not updating the UI but you've explained it all and so clearly... so thanks again!

  • Anonymous
    August 06, 2012
    I am new to Monodevelop as well as UBUNTU and now I am trying to develop an desktop application using c# to investigate the .Net parallelism (following this tutorial). I am stuck with one issue when i use Parallel.For loop. As of i read on the Internet, Dispatcher.beginInvoke will delegate the work done by worker thread to the UI thread. The article also says that if you don't use dispatcher it will through an error for the desktop applications. but it still working fine for me. I am not understanding what is happening here Here is the code: Parallel.For(2, 20, (i) => {   var result = SumRootN(i);   this.Dispatcher.BeginInvoke(new Action(() =>   textBlock1.Text += "root " + i.ToString() + " " +   result.ToString() + Environment.NewLine)   , null); }); If i take out "this.Dispatcher.BeginInvoke(new Action(() =>" statement still it is working as expected. but according to this link  it should not work. Developing environment Details: Monodevelop Version - monodevelop 2.8.6.3+dfsg-2 UBUNTU Version - 12.4 Need some help urgently!! Thanks for your time.

  • Anonymous
    August 19, 2012
    Nice article. Very easy to understand. I use Parallel Programming in .NET in my SEO scripts (www.seoblack-inside.com) Thank You.

  • Anonymous
    August 27, 2012
    Nice Article, But as a beginner im still having problems with the TASKS.

  • Anonymous
    August 28, 2012
    Good Job!

  • Anonymous
    November 03, 2012
    Thank you very much, very helpful post.

  • Anonymous
    November 27, 2012
    Great article!  Very useful. this new functionality on .net 4.0 it«s amazing, and safe a lot of time on programming

  • Anonymous
    February 18, 2013
    Could you pls provide similar article for .net 4.5, c# on win store app?

  • Anonymous
    March 07, 2013
    Very good and useful content. thank you Alex!

  • Anonymous
    March 09, 2013
    "On my 3-GHz dual-core 64-bit computer with 4 GB of RAM the program takes about 18 seconds to run" OMG, on my 3-GHz dual-core 64-bit computer with 4 GB of RAM the program takes 320 seconds and I bought my computer at the end of 2012!

  • Anonymous
    May 16, 2013
    The content was very helpful .This article really gave me the view of Tasks concept.Very graceful example and explanation.Keep posting.

  • Anonymous
    September 05, 2013
    Good article please keep posting like this and it really help to understand easily.

  • Anonymous
    September 06, 2013
    A clearly written and easy to understand intro to parallel programming. Thanks for writing it. :)

  • Anonymous
    October 12, 2013
    Hi Alexandra, Its awesome blog and it will help me alot in my programmes so please keep posting. Thanks

  • Anonymous
    November 19, 2013
    Hi Alexandra, Easy to understand, clear, well organized and showing daily troubles for a beginner.  Keep posting like that, please.

  • Anonymous
    November 20, 2013
    Excellent article for beginner, Thanks.

  • Anonymous
    December 10, 2013
    Please keep this coming. Also, if possible attach the downloadable samples for us to tweak it accordingly and play around with your code. Thanks again. very helpful.

  • Anonymous
    March 12, 2014
    Thanks. It is useful and I am now going on to the next one.

  • Anonymous
    March 22, 2014
    Excelent

  • Anonymous
    June 12, 2014
    Very nice kick start for TPL!!

  • Anonymous
    June 16, 2014
    Hi, actually I wrote the example but my computer is a core i7, 2.70 GHz and when I use the Parallel.For it seems to last longet than without this, I am not sure if I am making something wrong but it seems not always it increases the performance.

  • Anonymous
    September 16, 2014
    Thank you for this article. It was excellent. Many posts on parallel programming are way too complicated for a beginner.

  • Anonymous
    April 26, 2015
    Thanks for this article. It is easy to understand for a real beginner like me.

  • Anonymous
    June 24, 2015
    Very good explanation in simple and easy to understand way. Thank you.