Apesar da Microsoft estar trabalhando no .NET's Parallel Extensions desde 2007, ainda existem algumas funcionalidades que eles não tiveram tempo de implementar completamente no .NET 4.0. Algumas funcionalidades eram "muito específicas a alguns aplicativos para serem incluidas no núcleo do Framework" enquanto outras simplesmente precisavam ser testadas e ter feedback dos usuários. Stephen Toub continua,
Felizmente, na maioria desses casos, nós estavamos aptos a construir essas funcionalidades com as construções de paralelização providas no .NET 4, em alguns casos simplesmente utilizando tipos e métodos do .NET4, e em outros casos tomando vantagem dos pontos de extensibilidade providos no .NET 4 para o propósito explícito de possibilitar desenvolvedores a prover suas próprias funcionalidades customizadas aonde o Framework não suporta. Ao longo do tempo, nós acumulamos uma riqueza de código nisso, e nós decidimos mostrar a maior parte disso através do projeto ParallelExtensionsExtra disponível como parte dos nossos exemplos do .NET 4, que pode ser baixado no endereço http://code.msdn.microsoft.com/ParExtSamples.
Os exemplos de código cobrem uma vasta gama de funcionalidades. Alguns destaques incluem:
Uma implementação do IProducerConsumerCollection para o wrapper BlockingCollection. Esta interface serve para coleções thread-safe em cenários do tradicional produtor/consumidor. Isso não estava incluído no .NET 4.0 porque a semântica correta para a versão da BlockingCollection pode variar dependendo do que sua aplicação precisa.
Para trabalhar com os componentes COM que precisam de blocos de uma single-thread existe o StaTaskScheduler. A versão base do StaTaskScheduler é bem simples, ele simplesmente roda um número predefinido de threads STA e espera as tarefas executarem. Uma variante sugerida é com o uso de armazenamento local na thread para instanciar um objeto COM em cada thread que está rodando.
Para aqueles interessados no Framework Reactive Extensions, existe a método de extensão Task.ToObservable. Isso possibilita a inscrição a ser anexada no resultado de cada Task. Se a incrição é retirada antes da tarefa ser completada, então a tarefa é cancelada.
Um cenário mais complexo é o ReductionVariable. Ele contém um conjunto de valores, um por instância e por thread, para o uso em operações de redução. Baseados no armazenamento local na thread, isso necessita um pouco de sincronização entre as threads que estão ativas e as que estão a ser escaladas. Quando a operação de redução está completa, os valores podem ser enumerados para gerar um resultado final.