-
Notifications
You must be signed in to change notification settings - Fork 371
Missing syncronous methods for dotnet core? #367
Comments
Hi @tidyui, Thanks for bringing this up. You are right. Our NetCore/Netstandard support does not yet include Sync implementation of the APIs. Thanks! |
Were you able to continue developing in .net core with the asynchronous calls? I ported the sample over and it appears to be working in the simplest case. I was wondering if you ran into any other problems. Thank you, |
I wonder if there's any update on this. |
I simply decided to not support Azure storage until the implementation is complete:) |
Hi @TechInceptions , @tidyui We have had some conversations with the CLR team, who provided this guidance:
.NET Core team has chosen to not support a true sync api for the reasons listed above (resource consumption, etc.) Even if we implement a true sync, it would end up being sync over async at some level. For this reason, we believe that adding fake sync apis would be a hindrance and not a help to our customers. Please let us know if you have any feedback regarding this. |
Here is one example in HttpWebRequest implementation where the provided sync methods are not true sync but in fact sync over async(Note that HttpClient has never supported sync). |
Well basically I just want to create a storage provider implementing a given interface which is synchronous. Since the documentation previously stated that this was supported I just waited for it to be implemented, but if it's not going to be available in .NET Core I'll just block the async calls from within the Interface implementation. Regards |
You should support true sync because millions of operations, as coded in people's libraries, ARE synchronous (for all kinds of reasons). Regarding synchronicity, Ideally, APIs should have two paths: True Sync, and True Async. In the .NET world, "sync over async" is filled with anxiety - one never knows how it's going to turnout. Regarding the ".GetAwaiter.GetResult()" work around, is it more reliable that "Task.Run (()=> ... )" ? I suspect ".GetAwaiter.GetResult()" will lead to deadlocks in UI chained scenarios.
I have heard that argument before and I don't buy it. Isn't it better that the people with a better understanding of their own codebase do the tricky work of ensuring that something like "sync over async" works? Mark my words, as we try to create a "better .NET" by forcing async, we are actually creating a "worse .NET" by generating "sync over async" as a direct consequence. |
Let me explain the rationale. True sync is not an option for a library if it is consuming a library that does not support true sync, as is the case for us and .NET Core. (And anyway, true sync is something of a misnomer for APIs that make network calls, but that's a different discussion.) So we have two options: create a sync-over-async wrapper, or let the caller do it. But as we have seen, the official guidance and prevailing wisdom is that exposing a wrapper should be avoided. This is with good reason, and it's similar to avoiding an async API that wraps a synchronous invocation. Avoiding such APIs not only keeps the API surface clean, it also avoids confusion. Customers will think there is true support for sync or async and expose this in their own public interface only to discover later that the underlying implementation doesn't actually support it! So we have concluded that it is best to follow the prevailing wisdom in this case. You are correct that deadlock avoidance is essential, especially in sync-over-async scenarios, so let me say a little about how this is done. The deadlock issue arises when a thread calls an async method and then blocks waiting for the result, while the async method chain is waiting for the thread to free up so it can continue. The solution is to have the async method do its work in a different context where it won't be constrained by a limited pool of threads. This is done internally in the async method using ConfigureAwait, so deadlocks are avoided within the library itself. If you feel that true sync is important then you can bring this up at https://github.com/dotnet/corefx to get this supported in .NET Core. |
The sync is not an option. Very well. But imagine I am a beginner and there's a few documentation about Azure Storage and the usage of the synchronous methods. How should I guess on the usage of Async methods? Microsoft release the libraries without properly documenting and explaining it : There is any MS documentation on how to use Azure Tables with ASP.NET Core. Look what kind of "documentation" has Microsoft on async methods: looks like some ugly auto-generated text without any example. |
Please reconsider this - it's making our porting over from net4x to netstandard much more difficult. Sync methods also have their uses, particularly with e.g. scripts, where you want instant feedback. Having to continually force results is a pain for us and reduces readability of our code. |
Here's a concrete example where I'm bumping into this due to non-async .NET Core primitives: I would like an AzureBlobStorageFileProvider that implements IFileProvider against azure storage. I plan to use this with StaticFiles to serve them out of blob storage. IFileProvider.GetFileInfo and IFileInfo CreateReadStream are not async, therefore I can't be "async all the way". I believe GetAwaiter().GetResult() might work, but am also worried about threading issues related to that. IMO, either IFileProvider and IFileInfo should be Async or CloudBlob needs a non-async OpenRead() method. |
This also is a royal pain for the Azure Storage Type Provider - type providers run synchronously, so no matter how many async calls, we always need to get with a blocking call at the end. It's especially annoying where we currently use simple methods like I'm not suggesting that there isn't a good use for the async methods, but removing the other ones strikes me as overly prescriptive. |
The big problem is, this is not a new API, and the original Azure storage API did have these synchronous methods. Not only that, we all depended on that original API, and many of us wrote loads of code against that original API with syncrhronous methods, and that was often even before async had even become an official part of the platform. (Remember the Async Targeting Pack anyone?, it wasn't that long ago). While I have zealously converted my code-bases to async as far and often as possible, there's still good parts of many parts of our code pipelines (and that is always the problem with this, conversion causes beginning to end pipeline rewrite) that make synchronous calls. So I would suggest at least a compromise here. I mean it's noble and all to use this time to strip out the old way of doing things, but it seems to me there could be a compromise that fulfills that goal while still allowing parity with the API as it has existed.. So why not provide an extra netstandard (only) library, named maybe WindowsAzure.Storage.Synchronous, that is made up of extension methods that expose the missing synchronous API calls? This way would unencumber the main library, and make it clear to anyone using the synchronous methods (which may require a using statement that even states something like using ... .Synchronous) that this is not the best way going forward. Seems like this could be done fairly quickly, and allow millions of lines of code to upgrade quickly without unreasonably strong-arming them into updating end-to-end pipelines of code when the resources may not be there to do that. |
If people want to port to some libs to
would become
|
Yes, and in F# it becomes For various reasons I'm now tempted to dump the Azure SDK completely and just switch to the raw REST API, maybe using the rest codegen tool. |
Thanks, but it looks like I'm going to back out of this. I'm starting to find API differences other than just forcing sync, such as not finding an equivalent for CloudTable.CreateQuery. This is a real shame as it really raises the entry requirements and makes it hard to move to .Net Core. :( |
I'm new to the the .Net Core thing and .Net Standard, but not to the .net Framwork. Playing with the new stuff. I need a very long time to understand, why the "same" .Net Standard Libraries works on an .Net Core app, but not on a .Net FrameWork 4.7 console. Because of an mistery "Commit" MethodNot Implemented Exception. Perfomance is a good thing. But if compile works than the runtime should not throw linker errors. Tested with WebJobs - SDK preview. #if SYNC was real show stopper. |
Well, after enough discussion, following the lead set by HttpWebRequest we have decided to offer sync methods as sync-over-async. This is a time buffer for our users before we deprecate the sync APIs in future versions of the library. @copernicus365 , to keep it simpler for people, particularly those who are already using the library, our Netstandard2.0 support which includes the feature parity between desktop and Netcore, will leave the methods as-is, in the same namespace / binary of the split-per-service packages(split packages are in preview at the moment). Naturally, we’ll need to echo guidance in our docs by the .NET team about the benefits of converting to async, and try to make as clear as possible that it’s sync-over-async under the covers. Many thanks to everyone who took the time to chime in on this thread and give us feedback! One related note - for existing people who are already using the sync methods on .NET Desktop, these will also be moving to sync-over-async. We’re modifying the codebase to use HttpClient everywhere (both in desktop and in .NET Core), which doesn’t offer any sort of true sync. This is to get away from having separate implementations of everything (one with HttpWebRequest and one with HttpClient), which has led to many bugs and behavior differences between the different implementations. |
@erezvani1529 woohoo! Thank you guys for listening to our feedback!!! |
@erezvani1529 any ideas on when this will happen? |
I started a project in GitHub to create a sync wrapper around the newer API. This should help speed up porting considerably for people that want to get up and working quickly, without having to change any existing code. https://github.com/Mossharbor/AzureWorkArounds.Storage Install-Package Mossharbor.AzureWorkArounds.Storage |
Oh, this is awesome. I can start porting some older code over now. Thank you very much, team! |
I don't understand how the mentioned Indeed, I found this issue related to |
@seankearon |
It's a real shame that nearly two years after this issue, it's not been possible to revert this change. We're still in the situation that the net framework version of the same version of the SDK has sync methods but the netstandard version does not (as well as various overloads of the Table Query SDK being removed). |
I need table api functions now, not sure why they cleaned up Blob, File and Queue and Cosmos but not Table. |
This might be a stupid question, but after adding version
7.2.1
to my dotnet core 1.1 netstandard 1.6.1 project there are only async methods available even though all "getting started" guides clearly contains syncronous versions of the methods.Am I missing here or have they not been implemented yet for dotnet core?
Best regards
Håkan
The text was updated successfully, but these errors were encountered: