Aren't the guidelines of async/await usage in C# contradicting the concepts of good architecture and...











up vote
100
down vote

favorite
22












This question concerns the C# language, but I expect it to cover other languages such as Java or TypeScript.



Microsoft recommends best practices on using asynchronous calls in .NET. Among these recommendations, let's pick two:




  • change the signature of the async methods so that they return Task or Task<> (in TypeScript, that'd be a Promise<>)

  • change the names of the async methods to end with xxxAsync()


Now, when replacing a low-level, synchronous component by an async one, this impacts the full stack of the application. Since async/await has a positive impact only if used "all the way up", it means the signature and method names of every layer in the application must be changed.



A good architecture often involves placing abstractions between each layers, such that replacing low-level components by others is unseen by the upper-level components. In C#, abstractions take the form of interfaces. If we introduce a new, low-level, async component, each interface in the call stack needs to be either modified or replaced by a new interface. The way a problem is solved (async or sync) in an implementing class is not hidden (abstracted) to the callers anymore. The callers have to know if it's sync or async.



Aren't async/await best practices contradicting with "good architecture" principles?



Does it mean that each interface (say IEnumerable, IDataAccessLayer) needs their async counterpart (IAsyncEnumerable, IAsyncDataAccessLayer) such that they can be replaced in the stack when switching to async dependencies?



If we push the problem a little further, wouldn't it be simpler to assume every method to be async (to return a Task<> or Promise<>), and for the methods to synchronize the async calls when they're not actually async? Is this something to be expected from the future programming languages?










share|improve this question




















  • 5




    While this sounds like a great discussion question, I think this is too opinion-based to be answered here.
    – Euphoric
    Dec 5 at 8:42






  • 21




    @Euphoric: I think the problem scetched here goes deeper than the C# guidelines, that's just a symptom of the fact that changing parts of an application to asynchronous behaviour can have non-local effects on the overall system. So my gut tells me there must be a non-opinionated answer for this, based on technical facts. Hence, I encourage everyone here not to close this question too early, instead let us wait what answers will come (and if they are too opinionated, we can still vote for closing).
    – Doc Brown
    Dec 5 at 10:07








  • 25




    @DocBrown I think the deeper question here is "Can part of system be changed from synchronous to asynchronous without parts that depend on it also having to change?" I think the answer to that is clear "no". In that case, I don't see how "concepts of good architecture and layering" apply here.
    – Euphoric
    Dec 5 at 10:47






  • 6




    @Euphoric: sounds like a good basis for a non-opinionated answer ;-)
    – Doc Brown
    Dec 5 at 10:49






  • 4




    @Gherman: because C#, like a lot of languages, can't do overloading based on return type alone. You'd end up with async methods that have the same signature as their sync counterparts (not all can take a CancellationToken, and those that do may wish to supply a default). Removing the existing sync methods (and proactively breaking all code) is an obvious non-starter.
    – Jeroen Mostert
    Dec 7 at 9:13















up vote
100
down vote

favorite
22












This question concerns the C# language, but I expect it to cover other languages such as Java or TypeScript.



Microsoft recommends best practices on using asynchronous calls in .NET. Among these recommendations, let's pick two:




  • change the signature of the async methods so that they return Task or Task<> (in TypeScript, that'd be a Promise<>)

  • change the names of the async methods to end with xxxAsync()


Now, when replacing a low-level, synchronous component by an async one, this impacts the full stack of the application. Since async/await has a positive impact only if used "all the way up", it means the signature and method names of every layer in the application must be changed.



A good architecture often involves placing abstractions between each layers, such that replacing low-level components by others is unseen by the upper-level components. In C#, abstractions take the form of interfaces. If we introduce a new, low-level, async component, each interface in the call stack needs to be either modified or replaced by a new interface. The way a problem is solved (async or sync) in an implementing class is not hidden (abstracted) to the callers anymore. The callers have to know if it's sync or async.



Aren't async/await best practices contradicting with "good architecture" principles?



Does it mean that each interface (say IEnumerable, IDataAccessLayer) needs their async counterpart (IAsyncEnumerable, IAsyncDataAccessLayer) such that they can be replaced in the stack when switching to async dependencies?



If we push the problem a little further, wouldn't it be simpler to assume every method to be async (to return a Task<> or Promise<>), and for the methods to synchronize the async calls when they're not actually async? Is this something to be expected from the future programming languages?










share|improve this question




















  • 5




    While this sounds like a great discussion question, I think this is too opinion-based to be answered here.
    – Euphoric
    Dec 5 at 8:42






  • 21




    @Euphoric: I think the problem scetched here goes deeper than the C# guidelines, that's just a symptom of the fact that changing parts of an application to asynchronous behaviour can have non-local effects on the overall system. So my gut tells me there must be a non-opinionated answer for this, based on technical facts. Hence, I encourage everyone here not to close this question too early, instead let us wait what answers will come (and if they are too opinionated, we can still vote for closing).
    – Doc Brown
    Dec 5 at 10:07








  • 25




    @DocBrown I think the deeper question here is "Can part of system be changed from synchronous to asynchronous without parts that depend on it also having to change?" I think the answer to that is clear "no". In that case, I don't see how "concepts of good architecture and layering" apply here.
    – Euphoric
    Dec 5 at 10:47






  • 6




    @Euphoric: sounds like a good basis for a non-opinionated answer ;-)
    – Doc Brown
    Dec 5 at 10:49






  • 4




    @Gherman: because C#, like a lot of languages, can't do overloading based on return type alone. You'd end up with async methods that have the same signature as their sync counterparts (not all can take a CancellationToken, and those that do may wish to supply a default). Removing the existing sync methods (and proactively breaking all code) is an obvious non-starter.
    – Jeroen Mostert
    Dec 7 at 9:13













up vote
100
down vote

favorite
22









up vote
100
down vote

favorite
22






22





This question concerns the C# language, but I expect it to cover other languages such as Java or TypeScript.



Microsoft recommends best practices on using asynchronous calls in .NET. Among these recommendations, let's pick two:




  • change the signature of the async methods so that they return Task or Task<> (in TypeScript, that'd be a Promise<>)

  • change the names of the async methods to end with xxxAsync()


Now, when replacing a low-level, synchronous component by an async one, this impacts the full stack of the application. Since async/await has a positive impact only if used "all the way up", it means the signature and method names of every layer in the application must be changed.



A good architecture often involves placing abstractions between each layers, such that replacing low-level components by others is unseen by the upper-level components. In C#, abstractions take the form of interfaces. If we introduce a new, low-level, async component, each interface in the call stack needs to be either modified or replaced by a new interface. The way a problem is solved (async or sync) in an implementing class is not hidden (abstracted) to the callers anymore. The callers have to know if it's sync or async.



Aren't async/await best practices contradicting with "good architecture" principles?



Does it mean that each interface (say IEnumerable, IDataAccessLayer) needs their async counterpart (IAsyncEnumerable, IAsyncDataAccessLayer) such that they can be replaced in the stack when switching to async dependencies?



If we push the problem a little further, wouldn't it be simpler to assume every method to be async (to return a Task<> or Promise<>), and for the methods to synchronize the async calls when they're not actually async? Is this something to be expected from the future programming languages?










share|improve this question















This question concerns the C# language, but I expect it to cover other languages such as Java or TypeScript.



Microsoft recommends best practices on using asynchronous calls in .NET. Among these recommendations, let's pick two:




  • change the signature of the async methods so that they return Task or Task<> (in TypeScript, that'd be a Promise<>)

  • change the names of the async methods to end with xxxAsync()


Now, when replacing a low-level, synchronous component by an async one, this impacts the full stack of the application. Since async/await has a positive impact only if used "all the way up", it means the signature and method names of every layer in the application must be changed.



A good architecture often involves placing abstractions between each layers, such that replacing low-level components by others is unseen by the upper-level components. In C#, abstractions take the form of interfaces. If we introduce a new, low-level, async component, each interface in the call stack needs to be either modified or replaced by a new interface. The way a problem is solved (async or sync) in an implementing class is not hidden (abstracted) to the callers anymore. The callers have to know if it's sync or async.



Aren't async/await best practices contradicting with "good architecture" principles?



Does it mean that each interface (say IEnumerable, IDataAccessLayer) needs their async counterpart (IAsyncEnumerable, IAsyncDataAccessLayer) such that they can be replaced in the stack when switching to async dependencies?



If we push the problem a little further, wouldn't it be simpler to assume every method to be async (to return a Task<> or Promise<>), and for the methods to synchronize the async calls when they're not actually async? Is this something to be expected from the future programming languages?







c# architecture async






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 6 at 12:47









Peter Mortensen

1,11621114




1,11621114










asked Dec 5 at 8:22









corentinaltepe

612125




612125








  • 5




    While this sounds like a great discussion question, I think this is too opinion-based to be answered here.
    – Euphoric
    Dec 5 at 8:42






  • 21




    @Euphoric: I think the problem scetched here goes deeper than the C# guidelines, that's just a symptom of the fact that changing parts of an application to asynchronous behaviour can have non-local effects on the overall system. So my gut tells me there must be a non-opinionated answer for this, based on technical facts. Hence, I encourage everyone here not to close this question too early, instead let us wait what answers will come (and if they are too opinionated, we can still vote for closing).
    – Doc Brown
    Dec 5 at 10:07








  • 25




    @DocBrown I think the deeper question here is "Can part of system be changed from synchronous to asynchronous without parts that depend on it also having to change?" I think the answer to that is clear "no". In that case, I don't see how "concepts of good architecture and layering" apply here.
    – Euphoric
    Dec 5 at 10:47






  • 6




    @Euphoric: sounds like a good basis for a non-opinionated answer ;-)
    – Doc Brown
    Dec 5 at 10:49






  • 4




    @Gherman: because C#, like a lot of languages, can't do overloading based on return type alone. You'd end up with async methods that have the same signature as their sync counterparts (not all can take a CancellationToken, and those that do may wish to supply a default). Removing the existing sync methods (and proactively breaking all code) is an obvious non-starter.
    – Jeroen Mostert
    Dec 7 at 9:13














  • 5




    While this sounds like a great discussion question, I think this is too opinion-based to be answered here.
    – Euphoric
    Dec 5 at 8:42






  • 21




    @Euphoric: I think the problem scetched here goes deeper than the C# guidelines, that's just a symptom of the fact that changing parts of an application to asynchronous behaviour can have non-local effects on the overall system. So my gut tells me there must be a non-opinionated answer for this, based on technical facts. Hence, I encourage everyone here not to close this question too early, instead let us wait what answers will come (and if they are too opinionated, we can still vote for closing).
    – Doc Brown
    Dec 5 at 10:07








  • 25




    @DocBrown I think the deeper question here is "Can part of system be changed from synchronous to asynchronous without parts that depend on it also having to change?" I think the answer to that is clear "no". In that case, I don't see how "concepts of good architecture and layering" apply here.
    – Euphoric
    Dec 5 at 10:47






  • 6




    @Euphoric: sounds like a good basis for a non-opinionated answer ;-)
    – Doc Brown
    Dec 5 at 10:49






  • 4




    @Gherman: because C#, like a lot of languages, can't do overloading based on return type alone. You'd end up with async methods that have the same signature as their sync counterparts (not all can take a CancellationToken, and those that do may wish to supply a default). Removing the existing sync methods (and proactively breaking all code) is an obvious non-starter.
    – Jeroen Mostert
    Dec 7 at 9:13








5




5




While this sounds like a great discussion question, I think this is too opinion-based to be answered here.
– Euphoric
Dec 5 at 8:42




While this sounds like a great discussion question, I think this is too opinion-based to be answered here.
– Euphoric
Dec 5 at 8:42




21




21




@Euphoric: I think the problem scetched here goes deeper than the C# guidelines, that's just a symptom of the fact that changing parts of an application to asynchronous behaviour can have non-local effects on the overall system. So my gut tells me there must be a non-opinionated answer for this, based on technical facts. Hence, I encourage everyone here not to close this question too early, instead let us wait what answers will come (and if they are too opinionated, we can still vote for closing).
– Doc Brown
Dec 5 at 10:07






@Euphoric: I think the problem scetched here goes deeper than the C# guidelines, that's just a symptom of the fact that changing parts of an application to asynchronous behaviour can have non-local effects on the overall system. So my gut tells me there must be a non-opinionated answer for this, based on technical facts. Hence, I encourage everyone here not to close this question too early, instead let us wait what answers will come (and if they are too opinionated, we can still vote for closing).
– Doc Brown
Dec 5 at 10:07






25




25




@DocBrown I think the deeper question here is "Can part of system be changed from synchronous to asynchronous without parts that depend on it also having to change?" I think the answer to that is clear "no". In that case, I don't see how "concepts of good architecture and layering" apply here.
– Euphoric
Dec 5 at 10:47




@DocBrown I think the deeper question here is "Can part of system be changed from synchronous to asynchronous without parts that depend on it also having to change?" I think the answer to that is clear "no". In that case, I don't see how "concepts of good architecture and layering" apply here.
– Euphoric
Dec 5 at 10:47




6




6




@Euphoric: sounds like a good basis for a non-opinionated answer ;-)
– Doc Brown
Dec 5 at 10:49




@Euphoric: sounds like a good basis for a non-opinionated answer ;-)
– Doc Brown
Dec 5 at 10:49




4




4




@Gherman: because C#, like a lot of languages, can't do overloading based on return type alone. You'd end up with async methods that have the same signature as their sync counterparts (not all can take a CancellationToken, and those that do may wish to supply a default). Removing the existing sync methods (and proactively breaking all code) is an obvious non-starter.
– Jeroen Mostert
Dec 7 at 9:13




@Gherman: because C#, like a lot of languages, can't do overloading based on return type alone. You'd end up with async methods that have the same signature as their sync counterparts (not all can take a CancellationToken, and those that do may wish to supply a default). Removing the existing sync methods (and proactively breaking all code) is an obvious non-starter.
– Jeroen Mostert
Dec 7 at 9:13










5 Answers
5






active

oldest

votes

















up vote
108
down vote



accepted










What Color Is Your Function?



You may be interested in Bob Nystrom's What Color Is Your Function1.



In this article, he describes a fictional language where:




  • Each function has a color: blue or red.

  • A red function may call either blue or red functions, no issue.

  • A blue function may only call blue functions.


While fictitious, this happens quite regularly in programming languages:




  • In C++, a "const" method may only call other "const" methods on this.

  • In Haskell, a non-IO function may only call non-IO functions.

  • In C#, a sync function may only call sync functions2.


As you have realized, because of these rules, red functions tend to spread around the code base. You insert one, and little by little it colonizes the whole code base.



1Bob Nystrom, apart from blogging, is also part of the Dart team and has written this little Crafting Interpreters serie; highly recommended for any programming language/compiler afficionado.



2Not quite true, as you may call an async function and block until it returns, but...



Language Limitation



This is, essentially, a language/run-time limitation.



Language with M:N threading, for example, such as Erlang and Go, do not have async functions: each function is potentially async and its "fiber" will simply be suspended, swapped out, and swapped back in when it's ready again.



C# went with a 1:1 threading model, and therefore decided to surface synchronicity in the language to avoid accidentally blocking threads.



In the presence of language limitations, coding guidelines have to adapt.






share|improve this answer

















  • 4




    IO functions do have a tendency to spread, but with diligence, you can mostly isolate them to functions near (in the stack when calling) entry points of your code. You can do this by having those functions call the IO functions and then have other functions process the output from them and return any results needed for further IO. I find that this style makes my code bases much easier to manage and work with. I wonder if there's a corollary with synchronicity.
    – jpmc26
    Dec 5 at 17:35








  • 15




    What do you mean by "M:N" and "1:1" threading?
    – Captain Man
    Dec 5 at 19:44






  • 1




    @jpmc26: Mostly, indeed. Isolating I/O at the boundary also makes it easier to unit-test. The one special-case, though, is logging.
    – Matthieu M.
    Dec 5 at 20:47






  • 14




    @CaptainMan: 1:1 threading means mapping one application thread to one OS thread, this is the case in languages such as C, C++, Java or C#. By contrast, M:N threading means mapping M applications threads to N OS threads; in the case of Go, an application thread is called a "goroutine", in the case of Erlang, it's called an "actor", and you may also have heard of them as "green threads" or "fibers". They provide concurrency without requiring parallelism. Unfortunately the Wikipedia article on the topic is rather sparse.
    – Matthieu M.
    Dec 5 at 20:53








  • 1




    This is somewhat related but I also think this "function color" idea also applies to functions that block on input from the user, e.g., modal dialog boxes, message boxes, some forms of console I/O, etc, which are tools that the framework has had since the beginning.
    – jrh
    Dec 7 at 21:53




















up vote
81
down vote













You are right there is a contradiction here, but it is not the "best practices" being bad. It is because asynchronous function does essentially different thing than a synchronous one. Instead of waiting for the result from its dependencies (usually some IO) it creates a task to be handled by the main event loop. This is not a difference which can be well hidden under abstraction.






share|improve this answer



















  • 27




    The answer is as simple as this IMO. The difference between a synchronous and asynchronous process isn't an implementation detail - it's a semantically different contract.
    – Ant P
    Dec 5 at 17:33






  • 10




    @AntP: I disagree that it's that simple; it surfaces in the C# language, but not in the Go language for example. So this is not an inherent property of asynchronous processes, it's a matter of how asynchronous processes are modeled in the given language.
    – Matthieu M.
    Dec 6 at 9:39






  • 1




    @MatthieuM. Yes, but you can use async methods in C# to provide synchronous contracts too, if you want to. The only difference is that Go is asynchronous by default while C# is synchronous by default. async gives you the second programming model - async is the abstraction (what it actually does depends on runtime, task scheduler, synchronization context, awaiter implementation...).
    – Luaan
    Dec 9 at 7:33


















up vote
6
down vote













An asynchronous method behaves differently than one which is synchronous, as I'm sure you're aware. At runtime, to convert an async call to a synchronous one is trivial, but the opposite cannot be said. So therefore the logic then becomes, why don't we make async methods of every method which may require it and let the caller "convert" as necessary to a synchronous method?



In a sense it is like having a method which throws exceptions and another which is "safe" and won't throw even in case of error. At what point is the coder being excessive to provide these methods which otherwise can be converted one to another?



In this there are two schools of thought: one is to create multiple methods, each one calling another possibly private method allowing for the possibility of providing optional parameters or minor alterations to behavior such as being asynchronous. The other is to minimize interface methods to bare essentials leaving it up to the caller to perform the necessary modifications himself/herself.



If you're of the first school, there's a certain logic to dedicating a class towards synchronous and asynchronous calls in order to avoid doubling every call. Microsoft tends to favor this school of thought, and by convention, to remain consistent with the style favored by Microsoft, you too would have to have an Async version, in much the same way that interfaces almost always start with an "I". Let me stress that it isn't wrong, per se, because it is better to keep a consistent style in a project rather than do it "the right way" and radically change style for the development that you add to a project.



That said, I tend to favor the second school, which is to minimize interface methods. If I think a method may be called in an asynchronous way, the method for me is asynchronous. The caller can decide whether or not to wait for that task to finish before proceeding. If this interface is an interface to a library, there is more reasonable to do it this way to minimize the number of methods you'd need to deprecate or adjust. If the interface is for internal use in my project, I will add a method for every needed call throughout my project for the parameters provided and no "extra" methods, and even then, only if the behavior of the method isn't already covered by an existing method.



However, like many things in this field, it's largely subjective. Both approaches have their pros and cons. Microsoft also started the convention of adding letters indicative of type at the beginning of the variable name, and "m_" to indicate it is a member, leading to variable names like m_pUser. My point being that not even Microsoft is infallible, and can make mistakes too.



That said, if your project is following this Async convention, I would advise you to respect it and continue the style. And only once you're given a project of your own, you can write it in the best way you see fit.






share|improve this answer

















  • 6




    "At runtime, to convert an async call to a synchronous one is trivial" I'm not sure it is exactly so. In .NET, using .Wait() method and like can cause negative consequences, and in js, as far as I know, it is not possible at all.
    – max630
    Dec 5 at 10:00






  • 2




    @max630 I didn't say there aren't concurrent issues to consider, but if it was initially a synchronous task, chances are it's not creating deadlocks. That said, trivial does not mean "double click here to convert to synchronous". In js, you return a Promise instance, and call resolve on it.
    – Neil
    Dec 5 at 10:25








  • 2




    yeah its totally a pain in the arse to convert async back to sync
    – Ewan
    Dec 5 at 10:26






  • 4




    @Neil In javascript, even if you call Promise.resolve(x) and then add callbacks to it, those callbacks won't be executed immediately.
    – NickL
    Dec 5 at 16:54






  • 1




    @Neil if an interface exposes an asynchronous method, expecting that waiting on the Task won't create a deadlock isn't a good assumption. It's much better for the interface to show it is actually synchronous in the method signature, than a promise in the documentation that could change in a later version.
    – Carl Walsh
    Dec 6 at 20:49


















up vote
1
down vote













Let's imagine there is a way to enable you to call functions in an async way without changing their signature.



That would be really cool and no-one would recommend you change their names.



But, actual asynchronous functions, not just ones that await another async function, but the lowest level have some structure to them specific to their async nature. eg



public class HTTPClient
{
public HTTPResponse GET()
{
//send data
while(!timedOut)
{
//check for response
if(response) {
this.GotResponse(response);
}
this.YouCanWait();
}
}

//tell calling code that they should watch for this event
public EventHander GotResponse
//indicate to calling code that they can go and do something else for a bit
public EventHander YouCanWait;
}


It's those two bit of information that the calling code needs in order to run the code in an async way that things like Task and async encapsulate.



There is more than one way to do asynchronous functions, async Task is just one pattern built into the compiler via return types so that you don't have to manually link up the events






share|improve this answer




























    up vote
    0
    down vote













    I will address the main point in a less C#ness fashion and more generic :




    Aren't async/await best practices contradicting with "good architecture" principles?




    I would say that it just depends of the choice you make in the design of your API and what you let to the user.



    If you want one function of your API to be only async there is little interest into following the naming convention. Just always return Task<>/Promise<>/Future<>/... as return type, it is self documenting. If wants a synchronise answer, he will still be able to do that by waiting, but if he always do that, it make a bit of boilerplate.



    However if you make only your API sync, that mean that if a user want it to be async, he will have to manage the async part of it himself.



    This can make quite a lot of extra work, however it can also give more control to the user about how many concurrent call he allows, place timeout, retrys and so on.



    In a large system with a huge API, implementing most of them to be sync by default might be easier and more efficient than managing independently each part of your API, specially if they share ressources (filesystem, CPU, database, ...).



    In fact for the most complex parts, you could perfectly have two implementations of the same part of your API, one synchronous doing the handy stuff, one asynchronous relying on the synchronous one do handle stuff and only managing concurrency, loads, timeouts, and retries.



    Maybe someone else can share his experience with that because I lack experience with such systems.






    share|improve this answer

















    • 2




      @Miral You've used "call an async method from a sync method" in both possibilities.
      – Adrian Wragg
      Dec 6 at 11:37










    • @AdrianWragg So I did; my brain must have had a race condition. I'll fix it.
      – Miral
      Dec 7 at 2:13










    • It's the other way around; it's trivial to call an async method from a sync method, but it's impossible to call a sync method from an async method. (And where things completely fall apart is when someone tries to do the latter anyway, which can lead to deadlocks.) So if you had to pick one, async by default is the better choice. Unfortunately it's also the harder choice, because an async implementation can only call async methods.
      – Miral
      Dec 7 at 2:13










    • (And by this I of course mean a blocking sync method. You can call something that makes a pure CPU-bound calculation synchronously from an async method -- although you should try to avoid doing it unless you know you're in a worker context rather than a UI context -- but blocking calls that wait idle on a lock or for I/O or for another operation are a bad idea.)
      – Miral
      Dec 7 at 2:17











    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "131"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f382486%2farent-the-guidelines-of-async-await-usage-in-c-contradicting-the-concepts-of-g%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    5 Answers
    5






    active

    oldest

    votes








    5 Answers
    5






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    108
    down vote



    accepted










    What Color Is Your Function?



    You may be interested in Bob Nystrom's What Color Is Your Function1.



    In this article, he describes a fictional language where:




    • Each function has a color: blue or red.

    • A red function may call either blue or red functions, no issue.

    • A blue function may only call blue functions.


    While fictitious, this happens quite regularly in programming languages:




    • In C++, a "const" method may only call other "const" methods on this.

    • In Haskell, a non-IO function may only call non-IO functions.

    • In C#, a sync function may only call sync functions2.


    As you have realized, because of these rules, red functions tend to spread around the code base. You insert one, and little by little it colonizes the whole code base.



    1Bob Nystrom, apart from blogging, is also part of the Dart team and has written this little Crafting Interpreters serie; highly recommended for any programming language/compiler afficionado.



    2Not quite true, as you may call an async function and block until it returns, but...



    Language Limitation



    This is, essentially, a language/run-time limitation.



    Language with M:N threading, for example, such as Erlang and Go, do not have async functions: each function is potentially async and its "fiber" will simply be suspended, swapped out, and swapped back in when it's ready again.



    C# went with a 1:1 threading model, and therefore decided to surface synchronicity in the language to avoid accidentally blocking threads.



    In the presence of language limitations, coding guidelines have to adapt.






    share|improve this answer

















    • 4




      IO functions do have a tendency to spread, but with diligence, you can mostly isolate them to functions near (in the stack when calling) entry points of your code. You can do this by having those functions call the IO functions and then have other functions process the output from them and return any results needed for further IO. I find that this style makes my code bases much easier to manage and work with. I wonder if there's a corollary with synchronicity.
      – jpmc26
      Dec 5 at 17:35








    • 15




      What do you mean by "M:N" and "1:1" threading?
      – Captain Man
      Dec 5 at 19:44






    • 1




      @jpmc26: Mostly, indeed. Isolating I/O at the boundary also makes it easier to unit-test. The one special-case, though, is logging.
      – Matthieu M.
      Dec 5 at 20:47






    • 14




      @CaptainMan: 1:1 threading means mapping one application thread to one OS thread, this is the case in languages such as C, C++, Java or C#. By contrast, M:N threading means mapping M applications threads to N OS threads; in the case of Go, an application thread is called a "goroutine", in the case of Erlang, it's called an "actor", and you may also have heard of them as "green threads" or "fibers". They provide concurrency without requiring parallelism. Unfortunately the Wikipedia article on the topic is rather sparse.
      – Matthieu M.
      Dec 5 at 20:53








    • 1




      This is somewhat related but I also think this "function color" idea also applies to functions that block on input from the user, e.g., modal dialog boxes, message boxes, some forms of console I/O, etc, which are tools that the framework has had since the beginning.
      – jrh
      Dec 7 at 21:53

















    up vote
    108
    down vote



    accepted










    What Color Is Your Function?



    You may be interested in Bob Nystrom's What Color Is Your Function1.



    In this article, he describes a fictional language where:




    • Each function has a color: blue or red.

    • A red function may call either blue or red functions, no issue.

    • A blue function may only call blue functions.


    While fictitious, this happens quite regularly in programming languages:




    • In C++, a "const" method may only call other "const" methods on this.

    • In Haskell, a non-IO function may only call non-IO functions.

    • In C#, a sync function may only call sync functions2.


    As you have realized, because of these rules, red functions tend to spread around the code base. You insert one, and little by little it colonizes the whole code base.



    1Bob Nystrom, apart from blogging, is also part of the Dart team and has written this little Crafting Interpreters serie; highly recommended for any programming language/compiler afficionado.



    2Not quite true, as you may call an async function and block until it returns, but...



    Language Limitation



    This is, essentially, a language/run-time limitation.



    Language with M:N threading, for example, such as Erlang and Go, do not have async functions: each function is potentially async and its "fiber" will simply be suspended, swapped out, and swapped back in when it's ready again.



    C# went with a 1:1 threading model, and therefore decided to surface synchronicity in the language to avoid accidentally blocking threads.



    In the presence of language limitations, coding guidelines have to adapt.






    share|improve this answer

















    • 4




      IO functions do have a tendency to spread, but with diligence, you can mostly isolate them to functions near (in the stack when calling) entry points of your code. You can do this by having those functions call the IO functions and then have other functions process the output from them and return any results needed for further IO. I find that this style makes my code bases much easier to manage and work with. I wonder if there's a corollary with synchronicity.
      – jpmc26
      Dec 5 at 17:35








    • 15




      What do you mean by "M:N" and "1:1" threading?
      – Captain Man
      Dec 5 at 19:44






    • 1




      @jpmc26: Mostly, indeed. Isolating I/O at the boundary also makes it easier to unit-test. The one special-case, though, is logging.
      – Matthieu M.
      Dec 5 at 20:47






    • 14




      @CaptainMan: 1:1 threading means mapping one application thread to one OS thread, this is the case in languages such as C, C++, Java or C#. By contrast, M:N threading means mapping M applications threads to N OS threads; in the case of Go, an application thread is called a "goroutine", in the case of Erlang, it's called an "actor", and you may also have heard of them as "green threads" or "fibers". They provide concurrency without requiring parallelism. Unfortunately the Wikipedia article on the topic is rather sparse.
      – Matthieu M.
      Dec 5 at 20:53








    • 1




      This is somewhat related but I also think this "function color" idea also applies to functions that block on input from the user, e.g., modal dialog boxes, message boxes, some forms of console I/O, etc, which are tools that the framework has had since the beginning.
      – jrh
      Dec 7 at 21:53















    up vote
    108
    down vote



    accepted







    up vote
    108
    down vote



    accepted






    What Color Is Your Function?



    You may be interested in Bob Nystrom's What Color Is Your Function1.



    In this article, he describes a fictional language where:




    • Each function has a color: blue or red.

    • A red function may call either blue or red functions, no issue.

    • A blue function may only call blue functions.


    While fictitious, this happens quite regularly in programming languages:




    • In C++, a "const" method may only call other "const" methods on this.

    • In Haskell, a non-IO function may only call non-IO functions.

    • In C#, a sync function may only call sync functions2.


    As you have realized, because of these rules, red functions tend to spread around the code base. You insert one, and little by little it colonizes the whole code base.



    1Bob Nystrom, apart from blogging, is also part of the Dart team and has written this little Crafting Interpreters serie; highly recommended for any programming language/compiler afficionado.



    2Not quite true, as you may call an async function and block until it returns, but...



    Language Limitation



    This is, essentially, a language/run-time limitation.



    Language with M:N threading, for example, such as Erlang and Go, do not have async functions: each function is potentially async and its "fiber" will simply be suspended, swapped out, and swapped back in when it's ready again.



    C# went with a 1:1 threading model, and therefore decided to surface synchronicity in the language to avoid accidentally blocking threads.



    In the presence of language limitations, coding guidelines have to adapt.






    share|improve this answer












    What Color Is Your Function?



    You may be interested in Bob Nystrom's What Color Is Your Function1.



    In this article, he describes a fictional language where:




    • Each function has a color: blue or red.

    • A red function may call either blue or red functions, no issue.

    • A blue function may only call blue functions.


    While fictitious, this happens quite regularly in programming languages:




    • In C++, a "const" method may only call other "const" methods on this.

    • In Haskell, a non-IO function may only call non-IO functions.

    • In C#, a sync function may only call sync functions2.


    As you have realized, because of these rules, red functions tend to spread around the code base. You insert one, and little by little it colonizes the whole code base.



    1Bob Nystrom, apart from blogging, is also part of the Dart team and has written this little Crafting Interpreters serie; highly recommended for any programming language/compiler afficionado.



    2Not quite true, as you may call an async function and block until it returns, but...



    Language Limitation



    This is, essentially, a language/run-time limitation.



    Language with M:N threading, for example, such as Erlang and Go, do not have async functions: each function is potentially async and its "fiber" will simply be suspended, swapped out, and swapped back in when it's ready again.



    C# went with a 1:1 threading model, and therefore decided to surface synchronicity in the language to avoid accidentally blocking threads.



    In the presence of language limitations, coding guidelines have to adapt.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Dec 5 at 12:58









    Matthieu M.

    11.8k43755




    11.8k43755








    • 4




      IO functions do have a tendency to spread, but with diligence, you can mostly isolate them to functions near (in the stack when calling) entry points of your code. You can do this by having those functions call the IO functions and then have other functions process the output from them and return any results needed for further IO. I find that this style makes my code bases much easier to manage and work with. I wonder if there's a corollary with synchronicity.
      – jpmc26
      Dec 5 at 17:35








    • 15




      What do you mean by "M:N" and "1:1" threading?
      – Captain Man
      Dec 5 at 19:44






    • 1




      @jpmc26: Mostly, indeed. Isolating I/O at the boundary also makes it easier to unit-test. The one special-case, though, is logging.
      – Matthieu M.
      Dec 5 at 20:47






    • 14




      @CaptainMan: 1:1 threading means mapping one application thread to one OS thread, this is the case in languages such as C, C++, Java or C#. By contrast, M:N threading means mapping M applications threads to N OS threads; in the case of Go, an application thread is called a "goroutine", in the case of Erlang, it's called an "actor", and you may also have heard of them as "green threads" or "fibers". They provide concurrency without requiring parallelism. Unfortunately the Wikipedia article on the topic is rather sparse.
      – Matthieu M.
      Dec 5 at 20:53








    • 1




      This is somewhat related but I also think this "function color" idea also applies to functions that block on input from the user, e.g., modal dialog boxes, message boxes, some forms of console I/O, etc, which are tools that the framework has had since the beginning.
      – jrh
      Dec 7 at 21:53
















    • 4




      IO functions do have a tendency to spread, but with diligence, you can mostly isolate them to functions near (in the stack when calling) entry points of your code. You can do this by having those functions call the IO functions and then have other functions process the output from them and return any results needed for further IO. I find that this style makes my code bases much easier to manage and work with. I wonder if there's a corollary with synchronicity.
      – jpmc26
      Dec 5 at 17:35








    • 15




      What do you mean by "M:N" and "1:1" threading?
      – Captain Man
      Dec 5 at 19:44






    • 1




      @jpmc26: Mostly, indeed. Isolating I/O at the boundary also makes it easier to unit-test. The one special-case, though, is logging.
      – Matthieu M.
      Dec 5 at 20:47






    • 14




      @CaptainMan: 1:1 threading means mapping one application thread to one OS thread, this is the case in languages such as C, C++, Java or C#. By contrast, M:N threading means mapping M applications threads to N OS threads; in the case of Go, an application thread is called a "goroutine", in the case of Erlang, it's called an "actor", and you may also have heard of them as "green threads" or "fibers". They provide concurrency without requiring parallelism. Unfortunately the Wikipedia article on the topic is rather sparse.
      – Matthieu M.
      Dec 5 at 20:53








    • 1




      This is somewhat related but I also think this "function color" idea also applies to functions that block on input from the user, e.g., modal dialog boxes, message boxes, some forms of console I/O, etc, which are tools that the framework has had since the beginning.
      – jrh
      Dec 7 at 21:53










    4




    4




    IO functions do have a tendency to spread, but with diligence, you can mostly isolate them to functions near (in the stack when calling) entry points of your code. You can do this by having those functions call the IO functions and then have other functions process the output from them and return any results needed for further IO. I find that this style makes my code bases much easier to manage and work with. I wonder if there's a corollary with synchronicity.
    – jpmc26
    Dec 5 at 17:35






    IO functions do have a tendency to spread, but with diligence, you can mostly isolate them to functions near (in the stack when calling) entry points of your code. You can do this by having those functions call the IO functions and then have other functions process the output from them and return any results needed for further IO. I find that this style makes my code bases much easier to manage and work with. I wonder if there's a corollary with synchronicity.
    – jpmc26
    Dec 5 at 17:35






    15




    15




    What do you mean by "M:N" and "1:1" threading?
    – Captain Man
    Dec 5 at 19:44




    What do you mean by "M:N" and "1:1" threading?
    – Captain Man
    Dec 5 at 19:44




    1




    1




    @jpmc26: Mostly, indeed. Isolating I/O at the boundary also makes it easier to unit-test. The one special-case, though, is logging.
    – Matthieu M.
    Dec 5 at 20:47




    @jpmc26: Mostly, indeed. Isolating I/O at the boundary also makes it easier to unit-test. The one special-case, though, is logging.
    – Matthieu M.
    Dec 5 at 20:47




    14




    14




    @CaptainMan: 1:1 threading means mapping one application thread to one OS thread, this is the case in languages such as C, C++, Java or C#. By contrast, M:N threading means mapping M applications threads to N OS threads; in the case of Go, an application thread is called a "goroutine", in the case of Erlang, it's called an "actor", and you may also have heard of them as "green threads" or "fibers". They provide concurrency without requiring parallelism. Unfortunately the Wikipedia article on the topic is rather sparse.
    – Matthieu M.
    Dec 5 at 20:53






    @CaptainMan: 1:1 threading means mapping one application thread to one OS thread, this is the case in languages such as C, C++, Java or C#. By contrast, M:N threading means mapping M applications threads to N OS threads; in the case of Go, an application thread is called a "goroutine", in the case of Erlang, it's called an "actor", and you may also have heard of them as "green threads" or "fibers". They provide concurrency without requiring parallelism. Unfortunately the Wikipedia article on the topic is rather sparse.
    – Matthieu M.
    Dec 5 at 20:53






    1




    1




    This is somewhat related but I also think this "function color" idea also applies to functions that block on input from the user, e.g., modal dialog boxes, message boxes, some forms of console I/O, etc, which are tools that the framework has had since the beginning.
    – jrh
    Dec 7 at 21:53






    This is somewhat related but I also think this "function color" idea also applies to functions that block on input from the user, e.g., modal dialog boxes, message boxes, some forms of console I/O, etc, which are tools that the framework has had since the beginning.
    – jrh
    Dec 7 at 21:53














    up vote
    81
    down vote













    You are right there is a contradiction here, but it is not the "best practices" being bad. It is because asynchronous function does essentially different thing than a synchronous one. Instead of waiting for the result from its dependencies (usually some IO) it creates a task to be handled by the main event loop. This is not a difference which can be well hidden under abstraction.






    share|improve this answer



















    • 27




      The answer is as simple as this IMO. The difference between a synchronous and asynchronous process isn't an implementation detail - it's a semantically different contract.
      – Ant P
      Dec 5 at 17:33






    • 10




      @AntP: I disagree that it's that simple; it surfaces in the C# language, but not in the Go language for example. So this is not an inherent property of asynchronous processes, it's a matter of how asynchronous processes are modeled in the given language.
      – Matthieu M.
      Dec 6 at 9:39






    • 1




      @MatthieuM. Yes, but you can use async methods in C# to provide synchronous contracts too, if you want to. The only difference is that Go is asynchronous by default while C# is synchronous by default. async gives you the second programming model - async is the abstraction (what it actually does depends on runtime, task scheduler, synchronization context, awaiter implementation...).
      – Luaan
      Dec 9 at 7:33















    up vote
    81
    down vote













    You are right there is a contradiction here, but it is not the "best practices" being bad. It is because asynchronous function does essentially different thing than a synchronous one. Instead of waiting for the result from its dependencies (usually some IO) it creates a task to be handled by the main event loop. This is not a difference which can be well hidden under abstraction.






    share|improve this answer



















    • 27




      The answer is as simple as this IMO. The difference between a synchronous and asynchronous process isn't an implementation detail - it's a semantically different contract.
      – Ant P
      Dec 5 at 17:33






    • 10




      @AntP: I disagree that it's that simple; it surfaces in the C# language, but not in the Go language for example. So this is not an inherent property of asynchronous processes, it's a matter of how asynchronous processes are modeled in the given language.
      – Matthieu M.
      Dec 6 at 9:39






    • 1




      @MatthieuM. Yes, but you can use async methods in C# to provide synchronous contracts too, if you want to. The only difference is that Go is asynchronous by default while C# is synchronous by default. async gives you the second programming model - async is the abstraction (what it actually does depends on runtime, task scheduler, synchronization context, awaiter implementation...).
      – Luaan
      Dec 9 at 7:33













    up vote
    81
    down vote










    up vote
    81
    down vote









    You are right there is a contradiction here, but it is not the "best practices" being bad. It is because asynchronous function does essentially different thing than a synchronous one. Instead of waiting for the result from its dependencies (usually some IO) it creates a task to be handled by the main event loop. This is not a difference which can be well hidden under abstraction.






    share|improve this answer














    You are right there is a contradiction here, but it is not the "best practices" being bad. It is because asynchronous function does essentially different thing than a synchronous one. Instead of waiting for the result from its dependencies (usually some IO) it creates a task to be handled by the main event loop. This is not a difference which can be well hidden under abstraction.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 5 at 10:29

























    answered Dec 5 at 9:58









    max630

    1,770513




    1,770513








    • 27




      The answer is as simple as this IMO. The difference between a synchronous and asynchronous process isn't an implementation detail - it's a semantically different contract.
      – Ant P
      Dec 5 at 17:33






    • 10




      @AntP: I disagree that it's that simple; it surfaces in the C# language, but not in the Go language for example. So this is not an inherent property of asynchronous processes, it's a matter of how asynchronous processes are modeled in the given language.
      – Matthieu M.
      Dec 6 at 9:39






    • 1




      @MatthieuM. Yes, but you can use async methods in C# to provide synchronous contracts too, if you want to. The only difference is that Go is asynchronous by default while C# is synchronous by default. async gives you the second programming model - async is the abstraction (what it actually does depends on runtime, task scheduler, synchronization context, awaiter implementation...).
      – Luaan
      Dec 9 at 7:33














    • 27




      The answer is as simple as this IMO. The difference between a synchronous and asynchronous process isn't an implementation detail - it's a semantically different contract.
      – Ant P
      Dec 5 at 17:33






    • 10




      @AntP: I disagree that it's that simple; it surfaces in the C# language, but not in the Go language for example. So this is not an inherent property of asynchronous processes, it's a matter of how asynchronous processes are modeled in the given language.
      – Matthieu M.
      Dec 6 at 9:39






    • 1




      @MatthieuM. Yes, but you can use async methods in C# to provide synchronous contracts too, if you want to. The only difference is that Go is asynchronous by default while C# is synchronous by default. async gives you the second programming model - async is the abstraction (what it actually does depends on runtime, task scheduler, synchronization context, awaiter implementation...).
      – Luaan
      Dec 9 at 7:33








    27




    27




    The answer is as simple as this IMO. The difference between a synchronous and asynchronous process isn't an implementation detail - it's a semantically different contract.
    – Ant P
    Dec 5 at 17:33




    The answer is as simple as this IMO. The difference between a synchronous and asynchronous process isn't an implementation detail - it's a semantically different contract.
    – Ant P
    Dec 5 at 17:33




    10




    10




    @AntP: I disagree that it's that simple; it surfaces in the C# language, but not in the Go language for example. So this is not an inherent property of asynchronous processes, it's a matter of how asynchronous processes are modeled in the given language.
    – Matthieu M.
    Dec 6 at 9:39




    @AntP: I disagree that it's that simple; it surfaces in the C# language, but not in the Go language for example. So this is not an inherent property of asynchronous processes, it's a matter of how asynchronous processes are modeled in the given language.
    – Matthieu M.
    Dec 6 at 9:39




    1




    1




    @MatthieuM. Yes, but you can use async methods in C# to provide synchronous contracts too, if you want to. The only difference is that Go is asynchronous by default while C# is synchronous by default. async gives you the second programming model - async is the abstraction (what it actually does depends on runtime, task scheduler, synchronization context, awaiter implementation...).
    – Luaan
    Dec 9 at 7:33




    @MatthieuM. Yes, but you can use async methods in C# to provide synchronous contracts too, if you want to. The only difference is that Go is asynchronous by default while C# is synchronous by default. async gives you the second programming model - async is the abstraction (what it actually does depends on runtime, task scheduler, synchronization context, awaiter implementation...).
    – Luaan
    Dec 9 at 7:33










    up vote
    6
    down vote













    An asynchronous method behaves differently than one which is synchronous, as I'm sure you're aware. At runtime, to convert an async call to a synchronous one is trivial, but the opposite cannot be said. So therefore the logic then becomes, why don't we make async methods of every method which may require it and let the caller "convert" as necessary to a synchronous method?



    In a sense it is like having a method which throws exceptions and another which is "safe" and won't throw even in case of error. At what point is the coder being excessive to provide these methods which otherwise can be converted one to another?



    In this there are two schools of thought: one is to create multiple methods, each one calling another possibly private method allowing for the possibility of providing optional parameters or minor alterations to behavior such as being asynchronous. The other is to minimize interface methods to bare essentials leaving it up to the caller to perform the necessary modifications himself/herself.



    If you're of the first school, there's a certain logic to dedicating a class towards synchronous and asynchronous calls in order to avoid doubling every call. Microsoft tends to favor this school of thought, and by convention, to remain consistent with the style favored by Microsoft, you too would have to have an Async version, in much the same way that interfaces almost always start with an "I". Let me stress that it isn't wrong, per se, because it is better to keep a consistent style in a project rather than do it "the right way" and radically change style for the development that you add to a project.



    That said, I tend to favor the second school, which is to minimize interface methods. If I think a method may be called in an asynchronous way, the method for me is asynchronous. The caller can decide whether or not to wait for that task to finish before proceeding. If this interface is an interface to a library, there is more reasonable to do it this way to minimize the number of methods you'd need to deprecate or adjust. If the interface is for internal use in my project, I will add a method for every needed call throughout my project for the parameters provided and no "extra" methods, and even then, only if the behavior of the method isn't already covered by an existing method.



    However, like many things in this field, it's largely subjective. Both approaches have their pros and cons. Microsoft also started the convention of adding letters indicative of type at the beginning of the variable name, and "m_" to indicate it is a member, leading to variable names like m_pUser. My point being that not even Microsoft is infallible, and can make mistakes too.



    That said, if your project is following this Async convention, I would advise you to respect it and continue the style. And only once you're given a project of your own, you can write it in the best way you see fit.






    share|improve this answer

















    • 6




      "At runtime, to convert an async call to a synchronous one is trivial" I'm not sure it is exactly so. In .NET, using .Wait() method and like can cause negative consequences, and in js, as far as I know, it is not possible at all.
      – max630
      Dec 5 at 10:00






    • 2




      @max630 I didn't say there aren't concurrent issues to consider, but if it was initially a synchronous task, chances are it's not creating deadlocks. That said, trivial does not mean "double click here to convert to synchronous". In js, you return a Promise instance, and call resolve on it.
      – Neil
      Dec 5 at 10:25








    • 2




      yeah its totally a pain in the arse to convert async back to sync
      – Ewan
      Dec 5 at 10:26






    • 4




      @Neil In javascript, even if you call Promise.resolve(x) and then add callbacks to it, those callbacks won't be executed immediately.
      – NickL
      Dec 5 at 16:54






    • 1




      @Neil if an interface exposes an asynchronous method, expecting that waiting on the Task won't create a deadlock isn't a good assumption. It's much better for the interface to show it is actually synchronous in the method signature, than a promise in the documentation that could change in a later version.
      – Carl Walsh
      Dec 6 at 20:49















    up vote
    6
    down vote













    An asynchronous method behaves differently than one which is synchronous, as I'm sure you're aware. At runtime, to convert an async call to a synchronous one is trivial, but the opposite cannot be said. So therefore the logic then becomes, why don't we make async methods of every method which may require it and let the caller "convert" as necessary to a synchronous method?



    In a sense it is like having a method which throws exceptions and another which is "safe" and won't throw even in case of error. At what point is the coder being excessive to provide these methods which otherwise can be converted one to another?



    In this there are two schools of thought: one is to create multiple methods, each one calling another possibly private method allowing for the possibility of providing optional parameters or minor alterations to behavior such as being asynchronous. The other is to minimize interface methods to bare essentials leaving it up to the caller to perform the necessary modifications himself/herself.



    If you're of the first school, there's a certain logic to dedicating a class towards synchronous and asynchronous calls in order to avoid doubling every call. Microsoft tends to favor this school of thought, and by convention, to remain consistent with the style favored by Microsoft, you too would have to have an Async version, in much the same way that interfaces almost always start with an "I". Let me stress that it isn't wrong, per se, because it is better to keep a consistent style in a project rather than do it "the right way" and radically change style for the development that you add to a project.



    That said, I tend to favor the second school, which is to minimize interface methods. If I think a method may be called in an asynchronous way, the method for me is asynchronous. The caller can decide whether or not to wait for that task to finish before proceeding. If this interface is an interface to a library, there is more reasonable to do it this way to minimize the number of methods you'd need to deprecate or adjust. If the interface is for internal use in my project, I will add a method for every needed call throughout my project for the parameters provided and no "extra" methods, and even then, only if the behavior of the method isn't already covered by an existing method.



    However, like many things in this field, it's largely subjective. Both approaches have their pros and cons. Microsoft also started the convention of adding letters indicative of type at the beginning of the variable name, and "m_" to indicate it is a member, leading to variable names like m_pUser. My point being that not even Microsoft is infallible, and can make mistakes too.



    That said, if your project is following this Async convention, I would advise you to respect it and continue the style. And only once you're given a project of your own, you can write it in the best way you see fit.






    share|improve this answer

















    • 6




      "At runtime, to convert an async call to a synchronous one is trivial" I'm not sure it is exactly so. In .NET, using .Wait() method and like can cause negative consequences, and in js, as far as I know, it is not possible at all.
      – max630
      Dec 5 at 10:00






    • 2




      @max630 I didn't say there aren't concurrent issues to consider, but if it was initially a synchronous task, chances are it's not creating deadlocks. That said, trivial does not mean "double click here to convert to synchronous". In js, you return a Promise instance, and call resolve on it.
      – Neil
      Dec 5 at 10:25








    • 2




      yeah its totally a pain in the arse to convert async back to sync
      – Ewan
      Dec 5 at 10:26






    • 4




      @Neil In javascript, even if you call Promise.resolve(x) and then add callbacks to it, those callbacks won't be executed immediately.
      – NickL
      Dec 5 at 16:54






    • 1




      @Neil if an interface exposes an asynchronous method, expecting that waiting on the Task won't create a deadlock isn't a good assumption. It's much better for the interface to show it is actually synchronous in the method signature, than a promise in the documentation that could change in a later version.
      – Carl Walsh
      Dec 6 at 20:49













    up vote
    6
    down vote










    up vote
    6
    down vote









    An asynchronous method behaves differently than one which is synchronous, as I'm sure you're aware. At runtime, to convert an async call to a synchronous one is trivial, but the opposite cannot be said. So therefore the logic then becomes, why don't we make async methods of every method which may require it and let the caller "convert" as necessary to a synchronous method?



    In a sense it is like having a method which throws exceptions and another which is "safe" and won't throw even in case of error. At what point is the coder being excessive to provide these methods which otherwise can be converted one to another?



    In this there are two schools of thought: one is to create multiple methods, each one calling another possibly private method allowing for the possibility of providing optional parameters or minor alterations to behavior such as being asynchronous. The other is to minimize interface methods to bare essentials leaving it up to the caller to perform the necessary modifications himself/herself.



    If you're of the first school, there's a certain logic to dedicating a class towards synchronous and asynchronous calls in order to avoid doubling every call. Microsoft tends to favor this school of thought, and by convention, to remain consistent with the style favored by Microsoft, you too would have to have an Async version, in much the same way that interfaces almost always start with an "I". Let me stress that it isn't wrong, per se, because it is better to keep a consistent style in a project rather than do it "the right way" and radically change style for the development that you add to a project.



    That said, I tend to favor the second school, which is to minimize interface methods. If I think a method may be called in an asynchronous way, the method for me is asynchronous. The caller can decide whether or not to wait for that task to finish before proceeding. If this interface is an interface to a library, there is more reasonable to do it this way to minimize the number of methods you'd need to deprecate or adjust. If the interface is for internal use in my project, I will add a method for every needed call throughout my project for the parameters provided and no "extra" methods, and even then, only if the behavior of the method isn't already covered by an existing method.



    However, like many things in this field, it's largely subjective. Both approaches have their pros and cons. Microsoft also started the convention of adding letters indicative of type at the beginning of the variable name, and "m_" to indicate it is a member, leading to variable names like m_pUser. My point being that not even Microsoft is infallible, and can make mistakes too.



    That said, if your project is following this Async convention, I would advise you to respect it and continue the style. And only once you're given a project of your own, you can write it in the best way you see fit.






    share|improve this answer












    An asynchronous method behaves differently than one which is synchronous, as I'm sure you're aware. At runtime, to convert an async call to a synchronous one is trivial, but the opposite cannot be said. So therefore the logic then becomes, why don't we make async methods of every method which may require it and let the caller "convert" as necessary to a synchronous method?



    In a sense it is like having a method which throws exceptions and another which is "safe" and won't throw even in case of error. At what point is the coder being excessive to provide these methods which otherwise can be converted one to another?



    In this there are two schools of thought: one is to create multiple methods, each one calling another possibly private method allowing for the possibility of providing optional parameters or minor alterations to behavior such as being asynchronous. The other is to minimize interface methods to bare essentials leaving it up to the caller to perform the necessary modifications himself/herself.



    If you're of the first school, there's a certain logic to dedicating a class towards synchronous and asynchronous calls in order to avoid doubling every call. Microsoft tends to favor this school of thought, and by convention, to remain consistent with the style favored by Microsoft, you too would have to have an Async version, in much the same way that interfaces almost always start with an "I". Let me stress that it isn't wrong, per se, because it is better to keep a consistent style in a project rather than do it "the right way" and radically change style for the development that you add to a project.



    That said, I tend to favor the second school, which is to minimize interface methods. If I think a method may be called in an asynchronous way, the method for me is asynchronous. The caller can decide whether or not to wait for that task to finish before proceeding. If this interface is an interface to a library, there is more reasonable to do it this way to minimize the number of methods you'd need to deprecate or adjust. If the interface is for internal use in my project, I will add a method for every needed call throughout my project for the parameters provided and no "extra" methods, and even then, only if the behavior of the method isn't already covered by an existing method.



    However, like many things in this field, it's largely subjective. Both approaches have their pros and cons. Microsoft also started the convention of adding letters indicative of type at the beginning of the variable name, and "m_" to indicate it is a member, leading to variable names like m_pUser. My point being that not even Microsoft is infallible, and can make mistakes too.



    That said, if your project is following this Async convention, I would advise you to respect it and continue the style. And only once you're given a project of your own, you can write it in the best way you see fit.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Dec 5 at 9:16









    Neil

    19k3464




    19k3464








    • 6




      "At runtime, to convert an async call to a synchronous one is trivial" I'm not sure it is exactly so. In .NET, using .Wait() method and like can cause negative consequences, and in js, as far as I know, it is not possible at all.
      – max630
      Dec 5 at 10:00






    • 2




      @max630 I didn't say there aren't concurrent issues to consider, but if it was initially a synchronous task, chances are it's not creating deadlocks. That said, trivial does not mean "double click here to convert to synchronous". In js, you return a Promise instance, and call resolve on it.
      – Neil
      Dec 5 at 10:25








    • 2




      yeah its totally a pain in the arse to convert async back to sync
      – Ewan
      Dec 5 at 10:26






    • 4




      @Neil In javascript, even if you call Promise.resolve(x) and then add callbacks to it, those callbacks won't be executed immediately.
      – NickL
      Dec 5 at 16:54






    • 1




      @Neil if an interface exposes an asynchronous method, expecting that waiting on the Task won't create a deadlock isn't a good assumption. It's much better for the interface to show it is actually synchronous in the method signature, than a promise in the documentation that could change in a later version.
      – Carl Walsh
      Dec 6 at 20:49














    • 6




      "At runtime, to convert an async call to a synchronous one is trivial" I'm not sure it is exactly so. In .NET, using .Wait() method and like can cause negative consequences, and in js, as far as I know, it is not possible at all.
      – max630
      Dec 5 at 10:00






    • 2




      @max630 I didn't say there aren't concurrent issues to consider, but if it was initially a synchronous task, chances are it's not creating deadlocks. That said, trivial does not mean "double click here to convert to synchronous". In js, you return a Promise instance, and call resolve on it.
      – Neil
      Dec 5 at 10:25








    • 2




      yeah its totally a pain in the arse to convert async back to sync
      – Ewan
      Dec 5 at 10:26






    • 4




      @Neil In javascript, even if you call Promise.resolve(x) and then add callbacks to it, those callbacks won't be executed immediately.
      – NickL
      Dec 5 at 16:54






    • 1




      @Neil if an interface exposes an asynchronous method, expecting that waiting on the Task won't create a deadlock isn't a good assumption. It's much better for the interface to show it is actually synchronous in the method signature, than a promise in the documentation that could change in a later version.
      – Carl Walsh
      Dec 6 at 20:49








    6




    6




    "At runtime, to convert an async call to a synchronous one is trivial" I'm not sure it is exactly so. In .NET, using .Wait() method and like can cause negative consequences, and in js, as far as I know, it is not possible at all.
    – max630
    Dec 5 at 10:00




    "At runtime, to convert an async call to a synchronous one is trivial" I'm not sure it is exactly so. In .NET, using .Wait() method and like can cause negative consequences, and in js, as far as I know, it is not possible at all.
    – max630
    Dec 5 at 10:00




    2




    2




    @max630 I didn't say there aren't concurrent issues to consider, but if it was initially a synchronous task, chances are it's not creating deadlocks. That said, trivial does not mean "double click here to convert to synchronous". In js, you return a Promise instance, and call resolve on it.
    – Neil
    Dec 5 at 10:25






    @max630 I didn't say there aren't concurrent issues to consider, but if it was initially a synchronous task, chances are it's not creating deadlocks. That said, trivial does not mean "double click here to convert to synchronous". In js, you return a Promise instance, and call resolve on it.
    – Neil
    Dec 5 at 10:25






    2




    2




    yeah its totally a pain in the arse to convert async back to sync
    – Ewan
    Dec 5 at 10:26




    yeah its totally a pain in the arse to convert async back to sync
    – Ewan
    Dec 5 at 10:26




    4




    4




    @Neil In javascript, even if you call Promise.resolve(x) and then add callbacks to it, those callbacks won't be executed immediately.
    – NickL
    Dec 5 at 16:54




    @Neil In javascript, even if you call Promise.resolve(x) and then add callbacks to it, those callbacks won't be executed immediately.
    – NickL
    Dec 5 at 16:54




    1




    1




    @Neil if an interface exposes an asynchronous method, expecting that waiting on the Task won't create a deadlock isn't a good assumption. It's much better for the interface to show it is actually synchronous in the method signature, than a promise in the documentation that could change in a later version.
    – Carl Walsh
    Dec 6 at 20:49




    @Neil if an interface exposes an asynchronous method, expecting that waiting on the Task won't create a deadlock isn't a good assumption. It's much better for the interface to show it is actually synchronous in the method signature, than a promise in the documentation that could change in a later version.
    – Carl Walsh
    Dec 6 at 20:49










    up vote
    1
    down vote













    Let's imagine there is a way to enable you to call functions in an async way without changing their signature.



    That would be really cool and no-one would recommend you change their names.



    But, actual asynchronous functions, not just ones that await another async function, but the lowest level have some structure to them specific to their async nature. eg



    public class HTTPClient
    {
    public HTTPResponse GET()
    {
    //send data
    while(!timedOut)
    {
    //check for response
    if(response) {
    this.GotResponse(response);
    }
    this.YouCanWait();
    }
    }

    //tell calling code that they should watch for this event
    public EventHander GotResponse
    //indicate to calling code that they can go and do something else for a bit
    public EventHander YouCanWait;
    }


    It's those two bit of information that the calling code needs in order to run the code in an async way that things like Task and async encapsulate.



    There is more than one way to do asynchronous functions, async Task is just one pattern built into the compiler via return types so that you don't have to manually link up the events






    share|improve this answer

























      up vote
      1
      down vote













      Let's imagine there is a way to enable you to call functions in an async way without changing their signature.



      That would be really cool and no-one would recommend you change their names.



      But, actual asynchronous functions, not just ones that await another async function, but the lowest level have some structure to them specific to their async nature. eg



      public class HTTPClient
      {
      public HTTPResponse GET()
      {
      //send data
      while(!timedOut)
      {
      //check for response
      if(response) {
      this.GotResponse(response);
      }
      this.YouCanWait();
      }
      }

      //tell calling code that they should watch for this event
      public EventHander GotResponse
      //indicate to calling code that they can go and do something else for a bit
      public EventHander YouCanWait;
      }


      It's those two bit of information that the calling code needs in order to run the code in an async way that things like Task and async encapsulate.



      There is more than one way to do asynchronous functions, async Task is just one pattern built into the compiler via return types so that you don't have to manually link up the events






      share|improve this answer























        up vote
        1
        down vote










        up vote
        1
        down vote









        Let's imagine there is a way to enable you to call functions in an async way without changing their signature.



        That would be really cool and no-one would recommend you change their names.



        But, actual asynchronous functions, not just ones that await another async function, but the lowest level have some structure to them specific to their async nature. eg



        public class HTTPClient
        {
        public HTTPResponse GET()
        {
        //send data
        while(!timedOut)
        {
        //check for response
        if(response) {
        this.GotResponse(response);
        }
        this.YouCanWait();
        }
        }

        //tell calling code that they should watch for this event
        public EventHander GotResponse
        //indicate to calling code that they can go and do something else for a bit
        public EventHander YouCanWait;
        }


        It's those two bit of information that the calling code needs in order to run the code in an async way that things like Task and async encapsulate.



        There is more than one way to do asynchronous functions, async Task is just one pattern built into the compiler via return types so that you don't have to manually link up the events






        share|improve this answer












        Let's imagine there is a way to enable you to call functions in an async way without changing their signature.



        That would be really cool and no-one would recommend you change their names.



        But, actual asynchronous functions, not just ones that await another async function, but the lowest level have some structure to them specific to their async nature. eg



        public class HTTPClient
        {
        public HTTPResponse GET()
        {
        //send data
        while(!timedOut)
        {
        //check for response
        if(response) {
        this.GotResponse(response);
        }
        this.YouCanWait();
        }
        }

        //tell calling code that they should watch for this event
        public EventHander GotResponse
        //indicate to calling code that they can go and do something else for a bit
        public EventHander YouCanWait;
        }


        It's those two bit of information that the calling code needs in order to run the code in an async way that things like Task and async encapsulate.



        There is more than one way to do asynchronous functions, async Task is just one pattern built into the compiler via return types so that you don't have to manually link up the events







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Dec 5 at 11:16









        Ewan

        37.8k32983




        37.8k32983






















            up vote
            0
            down vote













            I will address the main point in a less C#ness fashion and more generic :




            Aren't async/await best practices contradicting with "good architecture" principles?




            I would say that it just depends of the choice you make in the design of your API and what you let to the user.



            If you want one function of your API to be only async there is little interest into following the naming convention. Just always return Task<>/Promise<>/Future<>/... as return type, it is self documenting. If wants a synchronise answer, he will still be able to do that by waiting, but if he always do that, it make a bit of boilerplate.



            However if you make only your API sync, that mean that if a user want it to be async, he will have to manage the async part of it himself.



            This can make quite a lot of extra work, however it can also give more control to the user about how many concurrent call he allows, place timeout, retrys and so on.



            In a large system with a huge API, implementing most of them to be sync by default might be easier and more efficient than managing independently each part of your API, specially if they share ressources (filesystem, CPU, database, ...).



            In fact for the most complex parts, you could perfectly have two implementations of the same part of your API, one synchronous doing the handy stuff, one asynchronous relying on the synchronous one do handle stuff and only managing concurrency, loads, timeouts, and retries.



            Maybe someone else can share his experience with that because I lack experience with such systems.






            share|improve this answer

















            • 2




              @Miral You've used "call an async method from a sync method" in both possibilities.
              – Adrian Wragg
              Dec 6 at 11:37










            • @AdrianWragg So I did; my brain must have had a race condition. I'll fix it.
              – Miral
              Dec 7 at 2:13










            • It's the other way around; it's trivial to call an async method from a sync method, but it's impossible to call a sync method from an async method. (And where things completely fall apart is when someone tries to do the latter anyway, which can lead to deadlocks.) So if you had to pick one, async by default is the better choice. Unfortunately it's also the harder choice, because an async implementation can only call async methods.
              – Miral
              Dec 7 at 2:13










            • (And by this I of course mean a blocking sync method. You can call something that makes a pure CPU-bound calculation synchronously from an async method -- although you should try to avoid doing it unless you know you're in a worker context rather than a UI context -- but blocking calls that wait idle on a lock or for I/O or for another operation are a bad idea.)
              – Miral
              Dec 7 at 2:17















            up vote
            0
            down vote













            I will address the main point in a less C#ness fashion and more generic :




            Aren't async/await best practices contradicting with "good architecture" principles?




            I would say that it just depends of the choice you make in the design of your API and what you let to the user.



            If you want one function of your API to be only async there is little interest into following the naming convention. Just always return Task<>/Promise<>/Future<>/... as return type, it is self documenting. If wants a synchronise answer, he will still be able to do that by waiting, but if he always do that, it make a bit of boilerplate.



            However if you make only your API sync, that mean that if a user want it to be async, he will have to manage the async part of it himself.



            This can make quite a lot of extra work, however it can also give more control to the user about how many concurrent call he allows, place timeout, retrys and so on.



            In a large system with a huge API, implementing most of them to be sync by default might be easier and more efficient than managing independently each part of your API, specially if they share ressources (filesystem, CPU, database, ...).



            In fact for the most complex parts, you could perfectly have two implementations of the same part of your API, one synchronous doing the handy stuff, one asynchronous relying on the synchronous one do handle stuff and only managing concurrency, loads, timeouts, and retries.



            Maybe someone else can share his experience with that because I lack experience with such systems.






            share|improve this answer

















            • 2




              @Miral You've used "call an async method from a sync method" in both possibilities.
              – Adrian Wragg
              Dec 6 at 11:37










            • @AdrianWragg So I did; my brain must have had a race condition. I'll fix it.
              – Miral
              Dec 7 at 2:13










            • It's the other way around; it's trivial to call an async method from a sync method, but it's impossible to call a sync method from an async method. (And where things completely fall apart is when someone tries to do the latter anyway, which can lead to deadlocks.) So if you had to pick one, async by default is the better choice. Unfortunately it's also the harder choice, because an async implementation can only call async methods.
              – Miral
              Dec 7 at 2:13










            • (And by this I of course mean a blocking sync method. You can call something that makes a pure CPU-bound calculation synchronously from an async method -- although you should try to avoid doing it unless you know you're in a worker context rather than a UI context -- but blocking calls that wait idle on a lock or for I/O or for another operation are a bad idea.)
              – Miral
              Dec 7 at 2:17













            up vote
            0
            down vote










            up vote
            0
            down vote









            I will address the main point in a less C#ness fashion and more generic :




            Aren't async/await best practices contradicting with "good architecture" principles?




            I would say that it just depends of the choice you make in the design of your API and what you let to the user.



            If you want one function of your API to be only async there is little interest into following the naming convention. Just always return Task<>/Promise<>/Future<>/... as return type, it is self documenting. If wants a synchronise answer, he will still be able to do that by waiting, but if he always do that, it make a bit of boilerplate.



            However if you make only your API sync, that mean that if a user want it to be async, he will have to manage the async part of it himself.



            This can make quite a lot of extra work, however it can also give more control to the user about how many concurrent call he allows, place timeout, retrys and so on.



            In a large system with a huge API, implementing most of them to be sync by default might be easier and more efficient than managing independently each part of your API, specially if they share ressources (filesystem, CPU, database, ...).



            In fact for the most complex parts, you could perfectly have two implementations of the same part of your API, one synchronous doing the handy stuff, one asynchronous relying on the synchronous one do handle stuff and only managing concurrency, loads, timeouts, and retries.



            Maybe someone else can share his experience with that because I lack experience with such systems.






            share|improve this answer












            I will address the main point in a less C#ness fashion and more generic :




            Aren't async/await best practices contradicting with "good architecture" principles?




            I would say that it just depends of the choice you make in the design of your API and what you let to the user.



            If you want one function of your API to be only async there is little interest into following the naming convention. Just always return Task<>/Promise<>/Future<>/... as return type, it is self documenting. If wants a synchronise answer, he will still be able to do that by waiting, but if he always do that, it make a bit of boilerplate.



            However if you make only your API sync, that mean that if a user want it to be async, he will have to manage the async part of it himself.



            This can make quite a lot of extra work, however it can also give more control to the user about how many concurrent call he allows, place timeout, retrys and so on.



            In a large system with a huge API, implementing most of them to be sync by default might be easier and more efficient than managing independently each part of your API, specially if they share ressources (filesystem, CPU, database, ...).



            In fact for the most complex parts, you could perfectly have two implementations of the same part of your API, one synchronous doing the handy stuff, one asynchronous relying on the synchronous one do handle stuff and only managing concurrency, loads, timeouts, and retries.



            Maybe someone else can share his experience with that because I lack experience with such systems.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Dec 5 at 15:44









            Walfrat

            3,074725




            3,074725








            • 2




              @Miral You've used "call an async method from a sync method" in both possibilities.
              – Adrian Wragg
              Dec 6 at 11:37










            • @AdrianWragg So I did; my brain must have had a race condition. I'll fix it.
              – Miral
              Dec 7 at 2:13










            • It's the other way around; it's trivial to call an async method from a sync method, but it's impossible to call a sync method from an async method. (And where things completely fall apart is when someone tries to do the latter anyway, which can lead to deadlocks.) So if you had to pick one, async by default is the better choice. Unfortunately it's also the harder choice, because an async implementation can only call async methods.
              – Miral
              Dec 7 at 2:13










            • (And by this I of course mean a blocking sync method. You can call something that makes a pure CPU-bound calculation synchronously from an async method -- although you should try to avoid doing it unless you know you're in a worker context rather than a UI context -- but blocking calls that wait idle on a lock or for I/O or for another operation are a bad idea.)
              – Miral
              Dec 7 at 2:17














            • 2




              @Miral You've used "call an async method from a sync method" in both possibilities.
              – Adrian Wragg
              Dec 6 at 11:37










            • @AdrianWragg So I did; my brain must have had a race condition. I'll fix it.
              – Miral
              Dec 7 at 2:13










            • It's the other way around; it's trivial to call an async method from a sync method, but it's impossible to call a sync method from an async method. (And where things completely fall apart is when someone tries to do the latter anyway, which can lead to deadlocks.) So if you had to pick one, async by default is the better choice. Unfortunately it's also the harder choice, because an async implementation can only call async methods.
              – Miral
              Dec 7 at 2:13










            • (And by this I of course mean a blocking sync method. You can call something that makes a pure CPU-bound calculation synchronously from an async method -- although you should try to avoid doing it unless you know you're in a worker context rather than a UI context -- but blocking calls that wait idle on a lock or for I/O or for another operation are a bad idea.)
              – Miral
              Dec 7 at 2:17








            2




            2




            @Miral You've used "call an async method from a sync method" in both possibilities.
            – Adrian Wragg
            Dec 6 at 11:37




            @Miral You've used "call an async method from a sync method" in both possibilities.
            – Adrian Wragg
            Dec 6 at 11:37












            @AdrianWragg So I did; my brain must have had a race condition. I'll fix it.
            – Miral
            Dec 7 at 2:13




            @AdrianWragg So I did; my brain must have had a race condition. I'll fix it.
            – Miral
            Dec 7 at 2:13












            It's the other way around; it's trivial to call an async method from a sync method, but it's impossible to call a sync method from an async method. (And where things completely fall apart is when someone tries to do the latter anyway, which can lead to deadlocks.) So if you had to pick one, async by default is the better choice. Unfortunately it's also the harder choice, because an async implementation can only call async methods.
            – Miral
            Dec 7 at 2:13




            It's the other way around; it's trivial to call an async method from a sync method, but it's impossible to call a sync method from an async method. (And where things completely fall apart is when someone tries to do the latter anyway, which can lead to deadlocks.) So if you had to pick one, async by default is the better choice. Unfortunately it's also the harder choice, because an async implementation can only call async methods.
            – Miral
            Dec 7 at 2:13












            (And by this I of course mean a blocking sync method. You can call something that makes a pure CPU-bound calculation synchronously from an async method -- although you should try to avoid doing it unless you know you're in a worker context rather than a UI context -- but blocking calls that wait idle on a lock or for I/O or for another operation are a bad idea.)
            – Miral
            Dec 7 at 2:17




            (And by this I of course mean a blocking sync method. You can call something that makes a pure CPU-bound calculation synchronously from an async method -- although you should try to avoid doing it unless you know you're in a worker context rather than a UI context -- but blocking calls that wait idle on a lock or for I/O or for another operation are a bad idea.)
            – Miral
            Dec 7 at 2:17


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Software Engineering Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f382486%2farent-the-guidelines-of-async-await-usage-in-c-contradicting-the-concepts-of-g%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            flock() on closed filehandle LOCK_FILE at /usr/bin/apt-mirror

            Mangá

             ⁒  ․,‪⁊‑⁙ ⁖, ⁇‒※‌, †,⁖‗‌⁝    ‾‸⁘,‖⁔⁣,⁂‾
”‑,‥–,‬ ,⁀‹⁋‴⁑ ‒ ,‴⁋”‼ ⁨,‷⁔„ ‰′,‐‚ ‥‡‎“‷⁃⁨⁅⁣,⁔
⁇‘⁔⁡⁏⁌⁡‿‶‏⁨ ⁣⁕⁖⁨⁩⁥‽⁀  ‴‬⁜‟ ⁃‣‧⁕‮ …‍⁨‴ ⁩,⁚⁖‫ ,‵ ⁀,‮⁝‣‣ ⁑  ⁂– ․, ‾‽ ‏⁁“⁗‸ ‾… ‹‡⁌⁎‸‘ ‡⁏⁌‪ ‵⁛ ‎⁨ ―⁦⁤⁄⁕