Proposal: Automatic generation of Sync/Async from single source #1991
Replies: 15 comments
-
I would suggest that this would be better implemented in tooling. For example visual studio or resharper could provide an option to automatically generate a non-async method from an async one. Certainly it feels a bit too unweildy for a language feature. It is not very nice to have methods mysteriously appear, and it would be very difficult to debug. Changing the signature of an asynchronous method, but not the synchronous method would cause the build to mysteriously fail. |
Beta Was this translation helpful? Give feedback.
-
I think that's not good enough, because it makes performing any changes to the method hard (and easy to forget to update the generated one). On the other hand, I agree this doesn't belong in the language itself. For example, right now the language doesn't know anything about the Perhaps the mythical code generators (#107) could help here? |
Beta Was this translation helpful? Give feedback.
-
@svick The compiler wouldn't necessarily need to know about CancellationToken, except possibly to propagate it down the call chain. That said, CancellationToken is the type of ambient data that shouldn't have to be manually propagated everywhere anyway--it should be in task-local storage (there are systems for this out there that copy the storage on every split of the call tree). Even without that, though, the presence of a CancellationToken would simply allow the implementation to support cancellation; not having it would not support cancellation, just as it does for Async functions today. |
Beta Was this translation helpful? Give feedback.
-
This would need a more fleshed out specification explaining the translation the compiler does, as well as how it both determines what to do in all these cases, as well as if/how users might be able to opt out when the translation is not correct for their needs. |
Beta Was this translation helpful? Give feedback.
-
Not really as they have |
Beta Was this translation helpful? Give feedback.
-
Possible stupid question here, but if you are creating an async version of a method, why create a synchronous one too? Why isn't the async version enough? |
Beta Was this translation helpful? Give feedback.
-
@DavidArno Why does the .NET framework provide both versions (in most cases)? If you're making a library, you have to provide both because async code has issues calling sync code and vice versa. See: https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html, https://msdn.microsoft.com/en-us/magazine/jj991977.aspx, https://blogs.msdn.microsoft.com/pfxteam/2011/01/13/await-and-ui-and-deadlocks-oh-my/, StephenCleary/AsyncEx#35, |
Beta Was this translation helpful? Give feedback.
-
One thing to keep in mind is that when you're doing async things, you're invoking platform APIs that call you back rather than platform APIs which block the thread. Asynchrony has overhead which is pure waste if you're going to block a thread anyway. In general, async overhead is an awesome tradeoff that gives you throughput by avoiding the blocking of any thread. |
Beta Was this translation helpful? Give feedback.
-
@jamesivie & @jnm2, Thanks. I naively thought that the framework added separate async methods purely for backwards compatibility reasons, rather than because there's good reasons to have both. Thanks for making me just that little less ignorant on this topic. 😃 |
Beta Was this translation helpful? Give feedback.
-
@jnm2 |
Beta Was this translation helpful? Give feedback.
-
@YairHalberstadt Some cases, yes. The only one I know of in the BCL is FileStream due to compatibility concerns. As you say, blocking a background thread is far from an ideal situation. |
Beta Was this translation helpful? Give feedback.
-
The only place I could see using this is for old libraries that has already committed to offering that duality. New code should simply not have a sync version most of the time. |
Beta Was this translation helpful? Give feedback.
-
IIRC |
Beta Was this translation helpful? Give feedback.
-
@scalablecory the framework itself is SEVERELY lacking async for even many basic operations. For example, you still can't open a disk or network file asynchronously, you can't get or set volume, directory, or file information asynchronously, and BinaryReader/Writer have no async functions. All of these are commonly used and obviously perform I/O. These are just a few of the places I happen to have run into when attempting to convert stuff to async, I'm sure there are many more. I don't know of any non-trivial libraries that are fully async due to these issues with the framework. My hope is that this change would at least allow people (including MS) to update libraries piecemeal as we all move to improve the way our code is written, and a simple recompile would take advantage of newly-exposed async functionality. |
Beta Was this translation helpful? Give feedback.
-
@jamesivie Those things (minus BinaryReader/Writer) are unfortunately synchronous due to the underlying Windows APIs not supporting async. C# and .NET are not a limiter here. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
As I've started writing libraries to support async, I've noticed how tedious it is to create synchronous and asynchronous methods for every library function, simply because they rely on underlying functionality that is both sync and async. I believe that the compiler could do all this work for me. For every async function, the sync function is simply a copy of the async function with awaits removed and calls made to non-async functions instead of sync functions. The only other thing that's different is cancelability (which is optional anyway). I believe the language would be greatly benefited by having the compiler generate (either project-wide or using special attributes) both the sync and async versions of functions from a single source specification. I believe that functions that wouldn't automatically "just work" using this kind of compiler logic are exceedingly rare (they would need to require asynchronous processing). The vast majority of async functions are a result of the zombie-virus nature of the async and do not require any sort of complex translation whatsoever. I propose that there be a project-level option to automatically generate the synchronous version of functions from the asynchronous version, or that the language be tweaked to automatically generate both synchronous and asynchronous code from a single source. Such a feature could also make it so that a simple recompile could take advantage of newly available async versions of functions added by the .NET team (For example, we desperately need a asynchronous version of System.IO.File.Open, but that doesn't exist today--if we had this feature and it was added, it could get used automatically). Please let me know if there is some complexity I'm missing here that makes this impossible. Even a simple attribute to explicitly apply to functions where this type of translation is desired and trivial would be greatly appreciated.
Beta Was this translation helpful? Give feedback.
All reactions