У Task есть свойство AsyncWaitHandle типа WaitHandle.
Составляешь массив из них + AuthResetEvent + CancellationToken.WaitHandle (чтобы была возможность отменить ожидание без timeout).
И передаешь в WaitHandle.WaitAny.
Можно и наоборот AuthResetEvent в Task обернуть, но мне такой способ меньше нравится. Но если нужно асинхронное ожидание, то следует смотреть в эту сторону.