Call a function on the main thread from the background thread

Update

I updated this question by including the source code for the Java implementation using the proposed SwingWorker class to achieve the same result as the Objective-C example. Hope this helps future adventurers.

Document myDoc = ...; Model myModel = ...; SwingWorker analyzeDocument = new SwingWorker<Dictionary, Void>() { @Override public Dictionary doInBackground() { return myDoc.analyze(); } @Override public void done() { try { stats = get(); myModel.setDict(stats); myModel.setNeedsDisplay(true); } catch(InterruptedException ex) { // log } catch(ExecutionException ex) { // log } } }; analyzeDocument.execute(); 

Original post

I am inexperienced when it comes to parallel programming, and I was hoping that someone could explain to me how I can achieve this.

In Objective-C (with GCD), you can do something like this:

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{ NSDictionary *stats = [myDoc analyze]; dispatch_async(dispatch_get_main_queue(), ^{ [myModel setDict:stats]; [myStatsView setNeedsDisplay:YES]; [stats release]; }); }); 

This code will execute [myDoc analyze] in the background thread, after the callback function, to update the user interface that will be executed in the main thread . In other words, the background thread sends an interrupt to the main thread, adding an anonymous function to the main thread's queue, which must be called. Obviously, I will not use anonymous functions in Java, but it is not.

I am interested in doing something with this in Java. I have a Runnable object that does a bunch of things on the file system. When it ends, I want to update the interface accordingly.

In order not to damage the main thread in this case (i.e. backgroundThread.join(); ), I set the background thread to execute a callback function to update the user interface. But this is not a good idea, I do not want the non-GUI thread to update the GUI.

Some other ideas that I was thinking about are polling, but it is like pumping loops from a window. In the same view, the use of futures is also not the answer. All this seems to be pursuing the goal of asynchronous action.

The only thing I can think of is to use SwingUtilities.invokeLater from the background thread and use it to update the GUI. But I'm curious in which thread this will be executed.

Maybe my perception is simply distorted, but it looks like it will be a pretty big part to leave. Am I just trying to do it wrong?

+4
source share
2 answers

Have you studied creating and using a SwingWorker object? This makes it easy to run code in the stream stream into the event stream, and in fact it is also a Future object, and therefore it can return a result, and you can use this result in your done() method to update the GUI on the event stream. You can even make calls in the Swing event stream in the middle of your run with a couple of publish / process methods.

For more on this, please check: Concurrency in Swing

+6
source

If you use Callable<V> instead of Runnable , you can return a value.

Also consider the Executors class.

+2
source

All Articles