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:
- Getting Started (this post)
- Task Schedulers and Synchronization Context
- Task Cancellation
- Blocking Collection and the Producer-Consumer Problem
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! ThanksAnonymous
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 YouAnonymous
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)? thanksAnonymous
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 againAnonymous
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.aspxAnonymous
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 removedAnonymous
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 niceAnonymous
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 removedAnonymous
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. DannyAnonymous
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 projectAnonymous
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.htmlAnonymous
June 13, 2010
The comment has been removedAnonymous
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 RusinaAnonymous
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 removedAnonymous
June 24, 2010
The comment has been removedAnonymous
June 24, 2010
Good article for beginnersAnonymous
June 25, 2010
The comment has been removedAnonymous
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. ScreenStarerAnonymous
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 DanielAnonymous
August 10, 2010
This is a simple and informative article which you have posted. Good one for getting a feeler of Parallel Programming and TPLAnonymous
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 removedAnonymous
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. ThanksAnonymous
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.comAnonymous
December 21, 2010
@Sandesh Here it is: blogs.msdn.com/.../async.aspxAnonymous
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 noviceAnonymous
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. ToddAnonymous
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 programmingAnonymous
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. ThanksAnonymous
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
ExcelentAnonymous
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.