PropertyInfo GetValue and Expression Cache GetValue
Problems


Both the reflection and expression-based approach fail to take null values into account (NullReferenceException).
They also fail to take types with indexers into account (TargetParameterCountException).
Hash-codes are not unique identifiers. Different properties (and objects in general) can have the same hash code - that just means that they might be equal. Use prop.MetadataToken in combination with the module they're declared in (prop.Module.ModuleVersionId).
Compiling expressions asynchronously makes this a lot more complex than it needs to be, and that complexity is not properly taken care of:


There's no guarantee that compilation will be finished when the next object is processed. This can result in multiple compilations for the same property. That's a waste of work.
The results of these compilations are added to a Dictionary, which is not thread-safe. In the best case, adding a key that already exists will throw an exception. In the worst case, the dictionary's internal state will become corrupted.
Those exceptions are not being caught. Before .NET Framework 4.5, that would've caused a crash, and in 4.5 and higher it may still do so, depending on certain settings.



Other improvements


Why does Execute take a sequence of items, instead of a single item? Flattening results is easy (data.SelectMany(service.Execute)), 'unflattening' is not - the caller would have to figure out the number of properties, and you'd have to write a method to split up a single sequence into sub-sequences.
Instead of doing ExpressionCache.ContainsKey(key), followed by ExpressionCache[key], use TryGetValue. This lets you check the presence of a key and get its associated value with a single lookup.
There's no point in making AddExpressionCacheAsync async. It's not doing any asynchronous work (that await Task.Yield() is useless). You're already calling this method from within a Task.Run call, so it'll be executed asynchronously anyway.
In GetValueGetter, use nameof(object.ToString) instead of "ToString".


Readability issues


Some names are not very descriptive: Execute -> GetPropertyValues, enums -> items, func -> compiledExpression, GetValueGetter -> CompileGetValueExpression.
There are several abbreviations that do not improve readability: e -> item, props -> properties, p -> property.