Simple is best alex mackey

Working with Tasks in VS2010

Task is a new class in .net 4 that is used to perform work in parallel. The Task Parallel Library (TPL) provides methods to create, schedule and synchronize tasks. Let's take a look at this functionality now.

How do tasks get scheduled?

1. When Tasks are created they are added to a global task queue
2. The task manager will by default create “worker” threads equal to the number of processors/cores on the machine
3. Each worker thread then picks up tasks from the global queue and will move it onto its local queue for execution
4. Each worker thread will then process the tasks on its queue
5. If a thread finishes all the work in its local queue it will steal tasks (Task Stealing) from other queues to ensure work is processed as quick as possible.  Note that tasks will steal work from the end of other task's queues to minimize the chance that the task is cached already.
 
Creating a new task
Tasks are very easy to schedule and I think more intuitive to work with than traditional threading classes.

There are a couple of ways to create a new task but before we see these we need to add the following using directive as all the task functionality is found in the System.Threading.Tasks namespace:

Using System.Threading.Tasks;

One way to create a new Task is with the Task.Factory.StartNew method. This method accepts an Action delegate and immediately starts a task.

Task task1 = Task.Factory.StartNew(() => StockService.CallSomeLongRunningService(Stocks[0]));

Another way you can start a task is to pass the code you want run into the Task’s constructor. The main difference here is that we have to explicitly start the Task when using this method. This could be useful for scenarios where you don’t want the task to start running straight away:

Task task2 = new Task(
 delegate
 {
     StockService.CallSomeLongRunningService(Stocks[0]);
 }
 );

task1.Start();
Console.ReadKey();

Task.Wait & Task.WaitAll
Task.Wait and Task.WaitAll allow you to pause the flow of execution until the tasks you specify have completed. For example when running the above code you may find the main program exits before the StockService has completed its work and output the results to the screen.

Below shows an example of using the Wait method to ensure task1 has completed and the WaitAll method to ensure tasks2,3 and 4 have finished:

Task task1 = new Task(delegate { StockService.CallSomeLongRunningService(Stocks[0]);});
Task task2 = new Task(delegate { StockService.CallSomeLongRunningService(Stocks[1]); });
Task task3 = new Task(delegate { StockService.CallSomeLongRunningService(Stocks[2]); });
Task task4 = new Task(delegate { StockService.CallSomeLongRunningService(Stocks[3]); });

task1.Start();
task2.Start();
task3.Start();
task4.Start();

task1.Wait();
Task.WaitAll(task2, task3, task4);

Console.ReadKey();

Task.WaitAny
You can also wait for the results of any task to complete with Task.WaitAny – perhaps you would use this if many Tasks are retrieving the same data from different sources:

Task.WaitAny(task2, task3, task4);

IsCompleted
You can also check if a task is completed by querying the IsCompleted property. This will return a boolean value indicating if the task has completed its work.

while (task1.IsCompleted == false)
{
 Console.WriteLine("Waiting on task 1");
}

ContinueWith
It is often necessary to specify work should be performed in a specific order . This can be declared in a fluent like manner with the ContinueWith method:

Task task3 = Task.Factory.StartNew(delegate{ StockService.CallSomeLongRunningService(Stocks[0]); })
.ContinueWith(delegate
{ StockService.CallSomeLongRunningService(Stocks[1]); })
.ContinueWith(delegate
{ StockService.CallSomeLongRunningService(Stocks[2]); });

Console.ReadKey();

Returning values from Tasks
You can retrieve a value that has been returned from a task by querying the result property:

var data = Task.Factory.StartNew(() =>  StockService.CallSomeLongRunningService(Stocks[0])).Result;
Console.WriteLine("Parallel task returned with value of {0}",data);

Alternatively you can use one of the generic Task classes and again query the result property:

Task<string> t = new Task<string>(delegate{return doSomething();} );
t.Start();
Console.WriteLine("Parallel task returned with value of {0}", t.Result);

What happens if the Task does not yet have a result?
If you try and access the result if the task has completed its work then the value will be returned. If however the task has not completed its work then the code will block until the task has completed. As you can probably predict this could slow your application down as the CLR waits for the return value. To minimize slow down you probably want to run the task as soon possible before you need access to the actual value.

Alex Mackey 30/06/2009, Comments (0)

Visual Studio 2010 Screencasts - First look and Visual Basic changes

I have recorded two screencasts on Visual Studio 2010:

VS2010 First look and IDE enhancements:
http://www.simpleisbest.co.uk/content/downloads/vs2010_01.wmv

Visual Basic Language enhancements:
http://www.simpleisbest.co.uk/content/downloads/vs2010_02.wmv

I plan on recording a number of screencasts and will shortly be working on the following:

  • C# Language & Variance changes
  • DLR
  • Parallelization
  • Customizing IDE
  • ASP.net & AJAX

Any suggestions/requests welcome!

Alex Mackey 27/05/2009, Comments (1)

Oslo May CTP

New Oslo CTP available:
http://www.microsoft.com/downloads/details.aspx?FamilyID=827122a5-3ca0-4389-a79e-87af37cbf60d&displaylang=en

I havent had a chance to review this properly yet but initial thoughts:

  • New version of Quadrant!
  • Intellipad much quicker than previous releases
  • Command line tools merged into m.exe
  • Minor syntax changes - most notably => used for declaring contents of extents

Alex Mackey 27/05/2009, Comments (0)

Speaker Feedback

This morning I got emailed the feedback from my recent talks at WebDD and DDD Belfast.

I was very interested to see this feedback as these were much larger events than I had talked at before. I found in smaller user groups people tend (but not always!) to be a bit kinder so with a larger and unknown audience I thought I would get a more honest assessment of my presentation.

The presentation I gave was an overview of all the new changes in VS2010 and .net 4. This was a bit different to previous presentations I have done given the scarce information available. The presentation was pre VS beta release so I only had the existing CTP to play with. I decided given the Nov CTP’s instability and slowness to not utilize it in my talk.

The negative comments could be summarized as the following:

  • Need more demos/too much Powerpoint
  • Too quick
  • Too much information
  • Need more detail
  • Make fonts bigger and close windows (totally agree sorry forgot to do this!)

These are all valid comments that I can learn from– apart from the demo one - if the CTP was worth showing I would have demoed it!
I think it’s probably impossible to please everyone. From the comments there were obviously some hard core devs who wanted much more detail – not sure this would have been so enjoyable or useful to everyone else. Maybe future session should make clear the level they are aimed at to avoid these disappointments.
Despite the suggestions I covered too much material too quickly many commented they liked the quick overview.

Lesson – you cannot please everyone!

These sort of comments can probably be minimized by writing a good session abstract.

In conclusion I will be doing a newer version of this presentation at DevEvening the end of Aug/very early Sep. The new presentation will be very much demo based now the Beta is here (maybe beta 2 by then?) and I will be limiting Power Point to the minimum. I think I will also pick fewer areas and go into more detail.

Overall very happy with feedback.

Alex Mackey 26/05/2009, Comments (0)

 Previous Posts