[swift-evolution] async void

Adam Kemp adam_kemp at apple.com
Mon Nov 13 11:53:41 CST 2017



> On Nov 12, 2017, at 1:47 PM, David Waite <david at alkaline-solutions.com> wrote:
> 
> From what I understand, the C# and Swift designs are different:
> 
> - C# async functions immediately return a task which can be enqueued to complete the work (including selecting which queue for UI cases, etc). Tasks have callback behavior attached to them.

Tasks in C# don’t represent something that can be enqueued. They represent work that is already taking place asynchronously, and the Task object can be used to install a callback or to fetch the result synchronously (ideally only after the work is already completed). You can’t use a Task to control which queue the work runs on (there may be no queue at all). You can use it to configure how an await will resume (essentially, which queue should be used), but that’s different from configuring on which queue the work will run.

> 
> - Swift async functions immediately enqueue to do work along with a callback function to be executed once work finishes. There is no first-class representation of a Future or the like, at least by default (a callback function could be promoted to a future). There is no support for selecting which queue work or the callback runs on (although your callback could immediately enqueue work on the appropriate thread, but this does increase latency in busy systems)
> 
> Assuming I got the above all correct there is no async Task vs async Void in swift, because a function which dispatches work to a queue without taking a callback just returns void. Those functions aren’t “async” at all, you can call them normally to dispatch work just as easily as you could call them within an async block, and they would have the same behavior. They also can’t be “awaited”, because there is no callback mechanism to tell when the work completes.

The async keyword isn’t used to denote a function that does work asynchronously. It’s a bit of a misnomer in that way. What it actually denotes is “this function can use the await keyword”. That’s why there is a concept of “async void” in C#: because it’s possible to use the await keyword in a function that can’t itself be awaited. It exists for the same reason that beginAsync exists in the proposal. My argument is just that it is easier to use the feature if you just allow non-awaitable functions to use await and have some kind of syntax for that.

> 
> Thats not to say I wouldn’t prefer the Task-type design, but it isn’t how most of the legacy asynchronous code is written to work (and would have some issues with GCD, since you can’t discover your current queue in order to enqueue more work there by default)

This has been discussed before. Getting the current queue is discouraged for client code because it’s usually an invalid thing to ask for (there isn’t just a single current queue), but there’s nothing wrong with the runtime or standard library using that to do meaningful things. Getting the current queue to resume an async task is a reasonable thing to do, and it could be built in. Look for the earlier emails from Pierre Habouzit about this topic for more information.



More information about the swift-evolution mailing list