var t1 = DoFooAsync(obj);
var t2 = DoBarAsync(obj);

var t = await WhenAnySuccessOrAllFail(t1, t2);

async Task WhenAnySuccessOrAllFail(params Task[] tasks)
{
    var remaining = new List<Task>(tasks);

    while (remaining.Count > 0)
    {
        var t = await Task.WhenAny(remaining);
        if (t.IsCompletedSuccessfully)
        {
            // Successful so return it
            return t;
        }

        // It failed, remove it from the remaining tasks to process
        remaining.Remove(t);
    }

    // Both failed (will bubble an aggregate exception)
    return await Task.WhenAll(tasks);
}