5 ms·
> There are very few ways to use Task.Result and Task.Wait correctly so the general advice is to completely avoid using them in your code. The article would ha
by pif 2y ago
> There are very few ways to use Task.Result and Task.Wait correctly so the general advice is to completely avoid using them in your code.
The article would have been interesting if it had proposed a solution to this problem, but instead they just brushed it away as if it was pointless.
- pif 2y agoTwo people already downvoted without replying. Tell me you have never developed complex software without actually telling me!
- mrkeen 2y agoI didn't down-vote. > There are very few ways to use Task.Result and Task.Wait correctly I don't even speak C# and I can read between the lines enough to see that they're saying 'waiting for a non-blocking method turns it into a blocking method, undoing the work of the library implementers who worked hard to provide you with non-blocking code'. Looking at the article, I think the solution was covered in the first sentence of the first list item: > Asynchrony is viral > Once you go async, all of your callers SHOULD be async,
- deleted 2y ago[deleted]
- pif 2y ago> Once you go async, all of your callers SHOULD be async, If you can't fathom that calling code could be written before, or independently from, or in a different domain than. called code, than you've never developed complex code.
- alkonaut 2y agoIndeed. Quite often the situation is this: I'm in code that cannot, under any circumstances, be made async. And I need to call an api, that is async and must stay async. So basically: you have to call async from a synchronous context. But I think perhaps the article correctly avoids the topic, because in 99% of cases when you think you need to do this, you don't. And having an easy googleable page with an easily copied recipe for doing so could do more harm than good. In the end it's going to be extremely rare that you can't bend over backwards to refactor your callsite to be async. E.g. you are in a constructor (which is sync) and want to call an async method. The solution isn't to wait on a result, the solution is obviously to not call it from the constructor. And that's the solution even if you have to refactor for a week instead of a blocking wait. But yeah I agree he could have included the answer, surrounded by big red warning sigs that you probably don't need to, or want to copy it. Perhaps the key clue is to give the good pointers to solving it properly. Just saying "you have to be async all the way" isn't really helpful. One key insight I got from somewhere was that identifying the async starting points was the key. E.g. for a desktop app, the realization that in 90% of cases your async "root" will be a GUI event, and that these event handlers in the GUI frameworks like WinForms or WPF can be async whenever you want. As a last resort, your main() method can be async.
- deleted 2y ago[deleted]
- Semaphor 2y agoThat’s what I was thinking. I mean, sure, I’d wish all our code was modern and new, but it’s not. And I can’t just magically make everything async, yet many devs *including MS* think modern code should not offer synchronous APIs. And so I need to call async APIs from synchronous code.
- Hawxy 2y agoThe article continues with all of the different ways you could do sync-over-async and all of them have downsides. There's no "good" solution that could be recommended. The community consensus is to do `GetAwaiter().GetResult()` and simply accept it's not an ideal usage.
- Kuinox 2y agoGetAwaiter().GetResult() can result in deadlocks. The ideal solution is to split the code and continue the execution through an event/continuation/queue, etc...
- pif 2y ago> The ideal solution is to split the code I'm sorry, it looks like you did not get the problem: you receive a Task, and you are in a sync environment, and you don't have control over these two constraints. How do you safely wait for the Task to complete?
- Semaphor 2y agoIt was more targeted at libraries not including sync methods anymore :(
- pif 2y agoIt's not a point of honour for MS developers that such a known problem has no good (TM) solution!
- Const-me 2y ago> a solution to this problem A solution is obvious – use await instead. Modern versions of the language even support async main function.
- pif 2y agoYou are ignoring the problem, like the article does. await implies an asynchronous function, but impedance mismatch between two different domains may need that you execute an async-something within a sync-something-else.
- Const-me 2y agoin .NET, the problem with that impedance mismatch is IMO very minor. I’ve been programming C# for living for more than a decade, and I can’t remember a single case when I needed to block a current thread waiting for a task to complete. Modern asp.net is designed in async-only way, no impedance mismatch there. async void functions are compatible with non-async delegates. This solves impedance mismatch for GUI frameworks or other event-driven apps. Just don’t forget to catch and handle exceptions from the async code inside, also for GUI apps show users that background operation is ongoing. The standard library exposes both flavours of APIs for files, sockets and many other built-in classes. You don’t have to use async APIs unless you want to.
- pif 2y agoI think you are confusing programming with developing software. Otherwise, we'll have just to agree to disagree.
- Salgat 2y agoUnfortunately the solution is very nuanced and boils down to being knowledgeable enough to know when Task.Result won't cause a deadlock, which is outside the scope of this guideline.
- Salgat 2y agoNot sure why the downvotes, .Result is avoided because it causes deadlocks, so you have to only use it when you are certain it won't create a deadlock condition. The most common way is to ensure it is already awaited (which defeats the point), however you can also use "var result = Task.Run(() => myTask).Result which will work without deadlocks since you're putting it on the threadpool but you lose the thread context so it won't work for UI tasks. It's not about trying to "undo" what the language developers created, but rather about you need to already be an expert if you want to avoid using await on async methods, which means you wouldn't need to be reading these guidelines in the first place.
- o_nate 2y agoMicrosoft could build a safe, approved low-level way of calling async from sync, maybe with a slight performance penalty, but if they did that, everyone with old crufty legacy code would drop that in and forget about upgrading to async, and they would have to support that method in perpetuity.