Entries of categorie .NET Help

"C# 4.0 in a Nutshell" parallel programming content

Joe Albahari, author of “C# 4.0 in a Nutshell”, has just published on his Web site the material from his book covering Parallel Extensions.  You can find his extensive article here:

http://www.albahari.com/threading/part5.aspx

Nice work, Joe.

 "C# 4.0 in a Nutshell" parallel programming content

FAQ :: TaskScheduler.UnobservedTaskException event doesn’t work?

Recall that if exceptions thrown from Task bodies  are left unobserved, they will be escalated.  In .NET 4, this means that TPL will throw them on the finalizer after the Task objects are available for garbage collection.  The UnobservedTaskException event on the TaskScheduler class was added as a last-resort method to observe such exceptions and prevent them from crashing the process.  Therefore, code like the following will not trigger the event:

 

TaskScheduler.UnobservedTaskException +=

    (object sender, UnobservedTaskExceptionEventArgs args) =>

{

    Console.WriteLine(“Caught it!”);

    args.SetObserved();

};

 

Task t = Task.Factory.StartNew(() =>

{

    throw new Exception(“ha!”);

});

 

try { t.Wait(); }

catch (Exception) { }

 

This is because the Task exception is already being correctly observed by calling Wait()!  There’s no reason to trigger the event, because the exception will not be escalated anyway.

 

Note that even if the Wait() call is removed from the code, the event will not trigger until the Task is available for garbage collection (and a collection actually happens).  Thus, the best way to see the event in action is to do something like this (replacing the try/catch block above):

 

((IAsyncResult)t).AsyncWaitHandle.WaitOne();

t = null;

GC.Collect();

GC.WaitForPendingFinalizers();

GC.Collect();

 

First, we wait for the Task to complete using its underlying wait handle; this does not observe exceptions like calling Task.Wait() does.  Then, we null the Task, making it available for garbage collection, and force a full collection.  See the attached file for all the code.

 FAQ :: TaskScheduler.UnobservedTaskException event doesn’t work?

Microsoft Biology Foundation 1.0 Released

It’s exciting to see that the Microsoft Biology Foundation 1.0 has been released!  You can read more about it here.  From MBF’s Web site:

“The Microsoft Biology Foundation (MBF) is a language-neutral bioinformatics toolkit built as an extension to the Microsoft .NET Framework, initially aimed at the area of Genomics research. Currently, it implements a range of parsers for common bioinformatics file formats; a range of algorithms for manipulating DNA, RNA, and protein sequences; and a set of connectors to biological web services such as NCBI BLAST. MBF is available under an open source license, and executables, source code, demo applications, and documentation are freely downloadable.”

Those of us on the Parallel Extensions team are particularly excited about this release because of MBF’s usage of the parallelism support in .NET 4.  Here are some relevant comments from Michael Zyskowski, a member of the MBF team in Microsoft Research:

“Microsoft Biology Foundation implements some powerful genomic alignment and assembly algorithms, including a novel De novo assembler called PaDeNA (Parallel De Novo Assembler), which employs the use of the latest .NET 4 Parallel Extensions capabilities.  In fact, many of the bioinformatics algorithms included in MBF are pleasingly parallel and take advantage of this great new technology.  Not only does the use of Parallel Extensions greatly improve the runtime performance and hardware utilization, it was also relatively easy to implement and retrofit into existing implementations.

The primary driver in parallel computation for MBF v1.0 is the increased capability of the Windows desktop already available in most research institutions.  We want to offer the researcher the ability to make better use of the computer that normally is dedicated to Office applications like Word, converting it to one that is capable of doing real, human-relevant health care research. This is just the start.”

Exciting stuff.  Congratulations to the MBF team!

 

 

 

 

 

 

 

 

 

 

 Microsoft Biology Foundation 1.0 Released

Using Cancellation Support in .NET Framework 4

The .NET Framework 4 introduces a new mechanism for cancellation of operations, based on new types CancellationToken and CancellationTokenSource. This cancellation mechanism is used across the parallel programming libraries: tasks, concurrent collections, and PLINQ queries.

Using Cancellation Support in .NET Framework 4, written by Mike Liddell, is an in-depth exploration of CancellationToken and CancellationTokenSource, how to make use of the cancellation support, and what are the common usage patterns that arise in practice.

(This paper and many more are available through the Parallel Computing Developer Center on MSDN at http://msdn.microsoft.com/en-us/concurrency/ee851578.aspx.)

 Using Cancellation Support in .NET Framework 4

PLINQ and Office Add-ins

Many different kinds of applications can benefit from multi-core parallelism, including add-ins to Microsoft Office.

Donny Amalo wrote a paper, PLINQ and Office Add-ins, where he demonstrates how to implement two parallel Microsoft Office add-ins using PLINQ:

  • A parallel Monte Carlo simulation add-in for Excel
  • A parallel custom spell checker add-in for Word

(This paper and many more are available through the Parallel Computing Developer Center on MSDN at http://msdn.microsoft.com/en-us/concurrency/ee851578.aspx.)

 PLINQ and Office Add ins

Integrating Parallelism with Windows Workflow Foundation

Despite the similarity in naming, the System.Threading.Tasks.Parallel class and the System.Activities.Statements.Parallel* activities in WF4 are largely orthogonal in the scenarios they address. However, WF4 activities and the new parallel programming types in .NET 4 can be used together to great advantage.

Ling Wo and Cristina Manu wrote a paper, Integrating Parallelism with Windows Workflow Foundation in the .NET Framework 4, that explores the similarities and differences between the two API sets, and demonstrates how to integrate the Task Parallel Library and WF4 to support the development of multi-threaded applications.

(This paper and many more are available through the Parallel Computing Developer Center on MSDN at http://msdn.microsoft.com/en-us/concurrency/ee851578.aspx.)

 Integrating Parallelism with Windows Workflow Foundation

Are you using parallelism with .NET? We’d love to know.

About six months ago, we posted on this blog to ask for details on if/how you’re using Parallel Extensions, and we got a great number of awesome responses… thanks!!  As that blog post has long since faded into distant memory, we’re asking again :)

Are you using Parallel Extensions, the parallelism support introduced with .NET 4? e.g. Parallel loops, Tasks, PLINQ, ConcurrentDictionary<>, ConcurrentQueue<>, Lazy<>, BlockingCollection<>, ManualResetEventSlim, ThreadLocal<T>, and so on?  Even if you’re using the unsupported .NET 3.5 release of Parallel Extensions, we’d love to hear from you.

Please get in touch by emailing me at stoub at microsoft dot com.  What are you building?  What functionality are you using?  What do you like?  What don’t you like?  What features/additions/changes would you like to see in the future?  etc.  Any and all feedback is welcome and encouraged.

Really looking forward to hearing from you!

Thanks,
Stephen

 Are you using parallelism with .NET? Wed love to know.

Concurrency Visualizer: A Case Study

Boby George and Pooja Nagpal – testers on the Parallel Computing Platform team responsible for the parallel programming support in .NET 4- built a parallel spell checker algorithm and used the Concurrency Visualizer to analyze and improve the performance and scalability of their implementation.

Optimizing Parallel Applications Using Concurrency Visualizer: A Case Study demonstrates how the CPU Utilization view, Threads view, and Cores view can help identify and analyze the scalability bottlenecks in your code.

(This paper and many more are available through the Parallel Computing Developer Center on MSDN at http://msdn.microsoft.com/en-us/concurrency/ee851578.aspx.)

 Concurrency Visualizer: A Case Study

PLINQ’s Ordering Model

In order to execute parallel queries as efficiently as possible, Parallel LINQ (PLINQ) treats ordering as optional. By default, PLINQ considers sequences to be unordered, unless the user explicitly opts into maintaining ordering using either the AsOrdered or the OrderBy operator.

Roy Patrick Tan wrote a detailed article that explains the precise ordering guarantees made by PLINQ for various types of queries: PLINQ’s Ordering Model

(This paper and many more are available through the Parallel Computing Developer Center on MSDN at http://msdn.microsoft.com/en-us/concurrency/ee851578.aspx.)

 PLINQ’s Ordering Model

"Task.Factory.StartNew" vs "new Task(…).Start"

With TPL, there are several ways to create and start a new task.  One way is to use the constructor for task followed by a call to the Start method, e.g.
        new Task(…).Start();
and the other is by using the StartNew method of TaskFactory, e.g.
        Task.Factory.StartNew(…);
This begs the question… when and why would you use one approach versus the other?

In general, I always recommend using Task.Factory.StartNew unless the particular situation provides a compelling reason to use the constructor followed by Start.  There are a few reasons I recommend this.  For one, it’s generally more efficient.  For example, we take a lot of care within TPL to make sure that when accessing tasks from multiple threads concurrently, the “right” thing happens.  A Task is only ever executed once, and that means we need to ensure that multiple calls to a task’s Start method from multiple threads concurrently will only result in the task being scheduled once.  This requires synchronization, and synchronization has a cost.  If you construct a task using the task’s constructor, you then pay this synchronization cost when calling the Start method, because we need to protect against the chance that another thread is concurrently calling Start.  However, if you use Task.Factory.StartNew, we know that the task will have already been scheduled by the time we hand the task reference back to your code, which means it’s no longer possible for threads to race to call Start, because every call to Start will fail.  As such, for StartNew we can avoid that additional synchronization cost and take a faster path for scheduling the task.

There are, however, some cases where creating a new task and then starting it is beneficial or even required (if there weren’t, we wouldn’t have provided the Start method).  One example is if you derive from Task.  This is an advanced case and there’s typically little need to derive from Task, but nevertheless, if you do derive from it the only way to schedule your custom task is to call the Start method, since in .NET 4 the Task.Factory.StartNew will always return the concrete Task or Task<TResult> types.  Another even more advanced use case is in dealing with certain race conditions.  Consider the need for a task’s body to have access to its own reference, such as if the task wanted to schedule a continuation off of itself.  You might try to accomplish that with code like:
    Task t = null;
    t = Task.Factory.StartNew(() =>
    {
        …
        t.ContinueWith(…);

    });
This code, however, is buggy.  There is a chance that the ThreadPool will pick up the scheduled task and execute it before the Task reference returned from StartNew is stored into t.  If that happens, the body of the task will see Task t as being null.  One way to fix this is to separate the creation and scheduling of the task, e.g.
    Task t = null;
    t = new Task(() =>
    {
        …
        t.ContinueWith(…);

    });
    t.Start();
Now, we know that t will in fact be properly initialized by the time the task body runs, because we’re not scheduling it until after it’s been set appropriately.

In short, there are certainly cases where taking the “new Task(…).Start()” approach is warranted.  But unless you find yourself in one of those cases, prefer TaskFactory.StartNew.

 "Task.Factory.StartNew" vs "new Task(...).Start"


Older entries » »