O objeto TaskCompletionSource permite encapsular tarefas de processamento. Isso permite a construção de métodos síncronos, que podem ser usados para paralelismo. Essa técnica é freqüentemente utilizada na construção de libraries , permitindo que o desenvolvedor decida pelo assincronismo e/ou paralelismo.

A construção básica consiste na criação de um método que retornará uma Task e essa Task será construída manualmente, sem a utilização de async/await.

Criação de uma Task para chamar método que simulará um heavy processing.

var heavyCalculationTask = Task.Run(
    function: () => HeavyCalculation.Run(
        iterations: iterations));

Este é o método que executa o heavy processing e retorna uma task com seu resultado.

var tcs = new TaskCompletionSource(); 

// Do Work tcs.SetResult(result: acc); 

return tcs.Task;

Confira o exemplo completo no GitHub: TaskCompletionSource