Say I have an interface and I want to expose both synchronous and asynchronous options for performing an action:
public interface MyInterface
{
Task<SomeResult> FetchSomeThingsAsync();
SomeResult FetchSomeThings();
}
Is it appropriate for the underlying implementation of FetchSomeThings
to be:
public SomeResult FetchSomeThings()
{
// Handle unwrapping AggregateException, if set
return FetchSomeThingsAsync().Result;
}
My gut is telling me that this isn't a great idea, but I'd really like to put my finger on why. My initial thoughts:
- this will actually use two threads, the blocked calling thread and a TPL thread
- this may be violating a caller's expectations for a synchronous method
My question: Is this bad? Does it have the potential to impact callers of the interface in a negative way? Are there issues with "correctness", is it simply wasteful from a performance standpoint, or is it even a good idea since it results in simpler code?
EDIT: Moving this from a comment I left below:
I frequently deal with cases where I use lower-level async I/O methods in my async implementation. Ex. The asynchronous version may need to call, for example, ExecuteRequestAsync()
on some lower level library, rather than simply wrapping the synchronous version in a task (like I might do for compute-bound operations). This is what has, historically, led me away from the opposite pattern -- implementing asynchronous methods by leveraging their synchronous counterparts.
To clarify the question a bit, lets assume that the asynchronous version requires a slightly more complex implementation than simply wrapping it in a Task.Run
.
ConfigureAwaiter
if you use asnyc-await. – CodesInChaos Apr 2 at 13:07