Похоже, что перегрузка Task.WaitAll с параметром timeout - это все, что вам нужно - если он возвращает true, то вы знаете, что все они завершены - в противном случае вы можете фильтровать по IsCompleted.
if (Task.WaitAll(tasks, myTimeout) == false)
{
tasks = tasks.Where(t => t.IsCompleted);
}
...