Based on these same concerns, how to do this using async/await ? func process() -> Void) {
loadWebResource("bigData.txt") { dataResource in //.... } printf("BigData Scheduled to load") loadWebResource("smallData.txt") { dataResource in //.... } printf("SmallData Scheduled to load") } Small data usually will finish first using GCD, but using async/await apear to be no way to schedule other things (on other Queue maybe) in the same function. I now this is about parallelism, but this is something that we will lose about GCD. I know the parallelism is not the focus, but is something important for the people migration from GCD. Maybe: yield loadWebResource("bigData.txt") // has a void return. yield loadWebResource("smallData.txt") // has a void return. I don't know if yield is the right keyword here but i think is important some way to "not" wait. Em seg, 21 de ago de 2017 às 15:04, Adam Kemp via swift-evolution < swift-evolution@swift.org> escreveu: > On Aug 18, 2017, at 8:38 PM, Chris Lattner <clatt...@nondot.org> wrote: > > On Aug 18, 2017, at 2:09 PM, Adam Kemp <adam.k...@apple.com> wrote: > > Maybe I’m still missing something, but how does this help when you are > interacting only with Swift code? If I were to write an asynchronous method > in Swift then how could I do the same thing that you propose that the > Objective-C importer do? That is, how do I write my function such that it > calls back on the same queue? > > > You’re right: if you’re calling something written in Swift, the ObjC > importer isn’t going to help you. > > However, if you’re writing an async function in Swift, then it is > reasonable for us to say what the convention is and expect you to follow > it. Async/await doesn’t itself help you implement an async operation: it > would be turtles all the way down… until you get to GCD, which is where you > do the async thing. > > As such, as part of rolling out async/await in Swift, I’d expect that GCD > would introduce new API or design patterns to support doing the right thing > here. That is TBD as far as the proposal goes, because it doesn’t go into > runtime issues. > > > The point I’m trying to make is that this is so important that I don’t > think it’s wise to leave it up to possible future library improvements, and > especially not to convention. Consider this example again from your > proposal: > > @IBAction func buttonDidClick(sender:AnyObject) { > doSomethingOnMainThread(); > beginAsync { > let image = await processImage() > imageView.image = image > } > doSomethingElseOnMainThread(); > } > > The line that assigns the image to the image view is very likely running > on the wrong thread. That code looks simple, but it is not safe. You would > have to insert a line like your other examples to ensure it’s on the right > thread: > > @IBAction func buttonDidClick(sender:AnyObject) { > doSomethingOnMainThread(); > beginAsync { > > let image = await processImage() > > await DispatchQueue.main.asyncCoroutine() > imageView.image = image > } > doSomethingElseOnMainThread(); > } > > > You would have to litter your code with that kind of stuff just in case > you’re on the wrong thread because there’s no way to tell where you’ll end > up after the await. In fact, this feature would make it much easier to end > up calling back on different queues in different circumstances because it > makes queue hopping invisible. From another example: > > func processImageData1() async -> Image { > > let dataResource = await loadWebResource("dataprofile.txt") > > let imageResource = await loadWebResource("imagedata.dat") > let imageTmp = await decodeImage(dataResource, imageResource) > let imageResult = await dewarpAndCleanupImage(imageTmp) > return imageResult > } > > > Which queue does a caller end up in? Whichever queue that last awaited > call gives you. This function does nothing to try to ensure that you always > end up on the same queue. If someone changes the code by adding or removing > one of those await calls then the final callback queue would change. If > there were conditionals in there that changed the code flow at runtime then > you could end up calling back on different queues depending on some runtime > state. > > IMO this would make doing safe async programming actually more difficult > to get right. It would be tedious and error prone. This simplified > async/await model may work well for JavaScript, which generally doesn’t > have shared mutable state across threads, but it seems dangerous in a > language that does. > > This isn’t a fair transformation though, and isn’t related to whether > futures is part of the library or language. The simplification you got > here is by making IBAction’s implicitly async. I don’t see that that is > possible, since they have a very specific calling convention (which returns > void) and are invoked by objc_msgSend. OTOH, if it were possible to do > this, it would be possible to do it with the proposal as outlined. > > > I didn’t mean to imply that all IBActions implicitly async. I just allowed > for an entire method to be async without being awaitable. In C# an async > void function is a “fire and forget” function. It executes in the context > of the caller’s thread/stack up until the first await, at which point it > returns to the caller like normal. The continuation just happens without > the caller knowing about it. The method signature is the same, and they are > callable by code that is unaware of async/await. C# supports async void > functions specifically for the event handler use case (and it is generally > discouraged for all other use cases). > > Your proposal already has async void methods, but they are awaitable. You > still need some ability to call an async method from a non-async method. > The way that you solved that is a special function (beginAsync), which as I > described earlier has some issues with readability. The other approach is > to have some way to decorate the entire function as “fire and forget”. > > The reason I linked these to library support is that the way that C# makes > this distinction is that an awaitable function must return a type that is > awaitable (it’s actually the traits of the return type that make it > awaitable, not the async keyword; you can await a function that is not > marked async). In C# a void method is not awaitable, even if it is marked > async. > > However, you’re right that these concepts don’t necessarily have to be > linked, and I shouldn’t have conflated them. You could also use some other > syntax to mark a non-awaitable method that is itself async. Maybe a > different keyword (deliberately ugly): > > @IBAction fire_and_forget_async func buttonDidClick(sender:AnyObject) { … } > > > To be clear, although this particular problem can be solved without > library support I think that both this problem and the queue-hopping > problem could be better solved by using a model closer to C#’s, with a > richer compiler transform that uses the return type. Swift could do this > using an awaitable protocol. > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution