Live data from Hacker News

On the proliferation of try, and soon, await (2020)

forums.swift.org

41–44 of 44 posts

Re: On the proliferation of try, and soon, await (2020)

#41

Earlier quoted context omitted.

C# uses “implicit context switch” on its async/await as it captures the current SynchronizationContext by default. On WPF/winforms/UWP and classic ASP there is one, so unless you other wise tell it, the await always comes back on the UI thread. Console and ASP net core have null as their SynchronizationContext.

> it captures the current SynchronizationContext by default. Which results in the majority of async code, which doesn't run in a UI context, needing to spam `.ConfigureAwait(false)` everywhere. It's the most visible wart in C# today - and no end of requests for a more succint alternative: https://github.com/dotnet/csharplang/discussions/645

I mostly deal with UI code so of course I like it how it is but couldn't anyone create, say, a BackgroundTask that extends Task where ConfigureAwait is defaulted to false?

Seems like a clear way to add it to the method signature and inform the caller and solve the issue with minimal work. Does that not work?

Re: On the proliferation of try, and soon, await (2020)

#42
post #41

Earlier quoted context omitted.

> it captures the current SynchronizationContext by default. Which results in the majority of async code, which doesn't run in a UI context, needing to spam `.ConfigureAwait(false)` everywhere. It's the most visible wart in C# today - and no end of requests for a more succint alternative: https://github.com/dotnet/csharplang/discussions/645

I mostly deal with UI code so of course I like it how it is but couldn't anyone create, say, a BackgroundTask that extends Task where ConfigureAwait is defaulted to false? Seems like a clear way to add it to the method signature and inform the caller and solve the issue with minimal work. Does that not work?

That wouldn't be appropriate: whether or not execution should resume on the same context is the caller's responsibility, not that of the function you're calling.

i.e. the same async method could be called from UI code and should resume on the UI thread immediately afterwards - or it could be called from library code - the method doesn't know that (nor does the person who wrote the method).

Re: On the proliferation of try, and soon, await (2020)

#43
post #41

Earlier quoted context omitted.

I mostly deal with UI code so of course I like it how it is but couldn't anyone create, say, a BackgroundTask that extends Task where ConfigureAwait is defaulted to false? Seems like a clear way to add it to the method signature and inform the caller and solve the issue with minimal work. Does that not work?

That wouldn't be appropriate: whether or not execution should resume on the same context is the caller's responsibility, not that of the function you're calling. i.e. the same async method could be called from UI code and should resume on the UI thread immediately afterwards - or it could be called from library code - the method doesn't know that (nor does the person who wrote the method).

I see your point but in reality the callee did already make the decision by using Task/TPL. As a language C# leaves the continuation functionality to the specific awaitable implementation. It seems like the natural place to make a different choice.

I do agree that I do not want to see it, though.

Re: On the proliferation of try, and soon, await (2020)

#44

The original poster says that these functions can't ever have invariants broken: > Functions that only mutate instances of well-encapsulated types through their public APIs. That includes nearly all functions that are not methods. > Methods of well-encapsulated types that only mutate non-member instances of other well-encapsulated types through their public APIs. This is incorrect! Consider the following function (in…

Your example doesn't fit into either of those two categories. In order to have an invariant, `ids`, `locations`, and `metadatas` would be need to be members of a well-encapsulated type, one which has `insert` as a method. So the first category is out since `insert` mutates the instance's members directly, without going through the instance's public API, and the second category doesn't apply since `insert` mutates its member instances, and not only non-member instances. I believe the author would agree that this function needs the "try" keyword to show that the invariants can be broken by an ill-placed throw.

The proposal is to keep the "try" keyword but allow functions to explicitly opt out so that "try" is not needed on every function call which can throw. The author suggested a "throws_anywhere" keyword after the argument list. My proposal would be to add "try blocks" which have the effect of allowing an exception to be rethrown anywhere inside the block (i.e. within a "try block" you can omit the normal "try" on a function call). The pattern:

  try {
    do_something();
    do_something_else();
  }
would be equivalent to:

  try do_something();
  try do_something_else();
So if you wanted the effect of "throws_anywhere" you just wrap the whole body of the function in one of these blocks. But you could also wrap just part of a function, for example just the part where the invariants are maintained, and require explicit handling in the parts where invariants are temporarily broken.
Post reply on HN