Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Another discussion where people don't get async/await, can't fathom why you would want a concurrency mechanism on a single thread and assume no one needs it.

UI programming, communication with the GPU, and cross runtime communication are good examples but I'm sure there are more.

Threads, green or otherwise, don't work for those cases but async/await does.



You can easily use threads with GUIs and I've written a bunch of GUI apps in the past that exploited threads quite effectively.


What popular GUI framework is multi threaded?


Depends what you mean by multi-threaded. There are plenty of frameworks that have some support for doing work on background threads.

Take JavaFX for example:

1. Rendering is done on a background thread in parallel with the app thread.

2. The class lib makes it easy to run background tasks that update the GUI to reflect progress and results.

3. You can construct widget trees on background threads and then pass them to the main UI thread only to attach them/make them visible.

With libs like ReactFX you can take event streams from the UI, map over them to a worker thread or pool of threads, and pass the results back to the UI thread.

A few years ago I did a video tutorial showing a few of these things, the code can be seen here:

https://github.com/mikehearn/KotlinFPWebinar/blob/master/src...

Basically this is a simple auto-complete widget. It takes a stream of values from a text field the user is typing in, reduces the frequency of changes (so if you type fast it doesn't constantly do work it's about to throw away) and then passes the heavy work of computing completions onto a background thread, then takes the results back onto the UI thread.

    val edits = EventStreams.valuesOf(edit.textProperty()).forgetful()
    val fewerEdits = edits.successionEnds(Duration.ofMillis(100)).filter { it.isNotBlank() }

    val inBackground = fewerEdits.threadBridgeFromFx(thread)
    val completions = inBackground.map { ngrams.complete(it) }
    val inForeground = completions.threadBridgeToFx(thread)

    val lastResult = inForeground.map {
        FXCollections.observableList(it)
    }.toBinding(FXCollections.emptyObservableList())
    completionsList.itemsProperty().bind(lastResult)
Now if you mean what UI libraries support writes to properties from arbitrary background threads without an explicit thread switch, I think the answer is only Win32 and Motif. But that's not a particularly important feature. JavaFX can catch the case if you access live UI from the wrong thread so such bugs are rarely an issue in practice. In particular it's easy to synchronize with the UI thread with a few simple helpers, e.g.:

    thread(name = "background") {
      while (true) {
        var speed = synchronizeWithUI { speedSlider.value }
        doSomeWork(speed)
      }
    }


I was referring to a UI system that did not differentiate a UI thread and could use things like pre-emptive scheduled tasks to access layout elements, etc.

Your example illustrates my point that you need to manually juggle threads if they are used directly. It ends up being the callback hell that async/await is the nice sugar for.


I don't see the callback hell. There aren't callbacks in the code samples I posted (the Rx-like chain is doing things that go well beyond callbacks).

Every UI toolkit has a concept of a UI thread because there has to be a single target for event notifications to be delivered to (keyboard/mouse/window), and they inherently have to be processed in sequence so they can't just be sprayed across multiple threads. However once you go beyond sequential event processing multi-threading becomes possible and as I said, JavaFX is a good example of that. Events like a window resize cause a reflow but then the actual work of generating the rendering commands is handled by a background thread (and architecturally it could be multiple render threads, that was just never done). Loading new UI can also be done on other threads. I think Blink also does some parallel rendering.

BTW, making property writes automatically thread-safe would be a trivial change to JavaFX but it's not really what you want. You need a concept of UI "transactions" to avoid the user seeing a UI that's half way through being modified by code. That's again not something specific to UI toolkits or threads vs async/await. It's inherent to the task. The "synchronizeWithUI" block in my code sample is doing that: you can think of it as committing some writes to the UI database.


How adequate is Swing (combined with JGoodies Binding or RxJava) compared to JavaFX in this regard?


I don't know JGoodies Binding so I can't help you with that, sorry. The concept is general. The code above uses Kotlin syntax for brevity but of course you can use Kotlin with Swing too.


It's definitely important to be able to manage a bunch of tasks explicitly in a single thread. If there are any other possible implementations of language features that result in the same binary and cause less trouble for the language's users, let's chat about those :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: