aspose file tools*
The moose likes Threads and Synchronization and the fly likes Callable Freezing Help Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Callable Freezing Help" Watch "Callable Freezing Help" New topic
Author

Callable Freezing Help

Ted Jones
Greenhorn

Joined: Jan 30, 2014
Posts: 14
I tried to create an easy first callable function, but it is locking up. I want to bring up an option pane and click OK or cancel. If OK, I want the returned true value to bring up another window so I can see it is working.

However, once I call the get() function, it locks up. I can't get past the first JOptionPane. I can't see the buttons from the callable JOptionPane, and I cannot get rid of the window. However, I can get the option screen to display correctly if I don't use the get method.



From my main


Any thoughts?
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42276
    
  64
I can't see the buttons from the callable JOptionPane, and I cannot get rid of the window.

That sounds odd. The code works as expected for me like this:


Ping & DNS - my free Android networking tools app
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Are you sure that all Swing code properly executes on the Event Dispatch thread? It looks like it doesn't, in which case I'd say all bets are off (it's not guaranteed to work).
Ted Jones
Greenhorn

Joined: Jan 30, 2014
Posts: 14
Martin Vajsar wrote:Are you sure that all Swing code properly executes on the Event Dispatch thread? It looks like it doesn't, in which case I'd say all bets are off (it's not guaranteed to work).


I think you are right. I was looking at the example above (which does what I want to do perfectly and is written better than I could) and it didn't have all of the exceptions that appear when I auto generate my exceptions. One of the exceptions that I'm getting is HeadLessException. I did some reading on that exception and that is because it isn't attached to a view? I was hoping to see something on preventing it, but nothing so far.

The difference is my code is a MVC project. The JOptionPane is in a Command package called by a controller. I didn't think that mattered in JAVA, but I think it is looking for a view to attach to (gut reaction).

Your replies prompted me to do a bit more research, so I was reading about "SwingUtilities.invokeLater((Runnable) ft);". However, that didn't make a difference. I think it isn't calling the "View" type class to generate the actual view of the dialog.

I apologize. If I thought that it being buries deep in a MVC would matter, I would have made it known. Let me know if you need me to post more code to help.

I'm going to keep looking, but if you see something, let me know.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

First of all, no need to apologize. We're glad to help.

Ted Jones wrote:One of the exceptions that I'm getting is HeadLessException. I did some reading on that exception and that is because it isn't attached to a view? I was hoping to see something on preventing it, but nothing so far.

The HeadlessException is documented like this:
Thrown when code that is dependent on a keyboard, display, or mouse is called in an environment that does not support a keyboard, display, or mouse.

I guess you're trying to run your code on an application server or a similar environment. It doesn't make sense to display dialog boxes there, the users are typically sitting at a different computer when using a web application. If you need user interaction, you'll need to design your application accordingly.

Ted Jones wrote:The difference is my code is a MVC project. The JOptionPane is in a Command package called by a controller. I didn't think that mattered in JAVA, but I think it is looking for a view to attach to (gut reaction).

I don't think that using MVC is the real cause of your problem. The MVC design pattern can be (and to great extent is) implemented in Swing applications, but also in a wide variety of different environments. It might help if you described the architecture of your application - and the requirement you're trying to implement - in greater detail.
Ted Jones
Greenhorn

Joined: Jan 30, 2014
Posts: 14
Alright, I was able to duplicate it in a second program. It just took me a while to create it. This is actually my first java program all on my own, so don't judge my coding too much. However, all suggestions are welcome.

I have 4 packages.

com.main
App.java


MainProgram.java


MainView.java


com.main.Commands
WaitForUserInput.java

com.main.Controller
MainController.java

com.main.Listener
SpecialListener.java
Ted Jones
Greenhorn

Joined: Jan 30, 2014
Posts: 14
When I simplified it, ironically, when I commented out the JOptionPane in the Callable, the second JOptionPane works. It is just in the Callable that the JOptionPane doesn't work.
Maxim Karvonen
Ranch Hand

Joined: Jun 14, 2013
Posts: 103
    
  11
Ted Jones wrote:It is just in the Callable that the JOptionPane doesn't work.

Yes, but not because it is inside Callable. Real problem is that code in your callable (WaitForUserInput) is not executed on an EDT thread. It is executed on executor thread. To add more problems, you are blocking an EDT by waiting for the execution result in runSpecialCoding method.

You should seriously consider interaction with an UI thread:
* Detect and document, which methods will be called only on an EDT and which are not.
* Use SwingUtilities.invokeAndWait/ SwingUtilities.invokeLater to interact with GUI from a non-EDT thread.
* Never wait for anything on EDT thread. And never perform potentially-long-lasting operations (reading a file, connecting to a server, etc.) on an EDT. Design such "long" operations to receive a callback which should be called after task execution. Perform all required operations only in callback and using invokeLater. Or document that calling callback methods is permitted only on EDT.
Ted Jones
Greenhorn

Joined: Jan 30, 2014
Posts: 14
Maxim Karvonen wrote:
Ted Jones wrote:It is just in the Callable that the JOptionPane doesn't work.

Yes, but not because it is inside Callable. Real problem is that code in your callable (WaitForUserInput) is not executed on an EDT thread. It is executed on executor thread. To add more problems, you are blocking an EDT by waiting for the execution result in runSpecialCoding method.

You should seriously consider interaction with an UI thread:
* Detect and document, which methods will be called only on an EDT and which are not.
* Use SwingUtilities.invokeAndWait/ SwingUtilities.invokeLater to interact with GUI from a non-EDT thread.
* Never wait for anything on EDT thread. And never perform potentially-long-lasting operations (reading a file, connecting to a server, etc.) on an EDT. Design such "long" operations to receive a callback which should be called after task execution. Perform all required operations only in callback and using invokeLater. Or document that calling callback methods is permitted only on EDT.


So, I started reading and I didn't know that JAVA has three types pf threads. The one I'm working with is a worker thread, but needs to be a event dispatch thread.
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html

However, I'm still a bit lost.

As you see above, I do have an invoke later. However, it doesn't do anything to help.

I tried to change the code to have the invokelater inside, but that didn't make a difference.



How do I create it as a EDT thread? I can see a test to see if it is, but not how to generate it as one:
javax.swing.SwingUtilities.isEventDispatchThread

Or... if it works in runnable (which I changed the class to a runnable and it does work), how do I error check and return a variable?
Maxim Karvonen
Ranch Hand

Joined: Jun 14, 2013
Posts: 103
    
  11
You have used invokeLater in the first example. And used it correctly to initialize GUI inside an EDT. But that was not sufficient. You should perform all swing-related operations from an EDT, not only an initialization.

Your new code does not work due to a deadlock I already mentioned. EDT waits for WaitForUserInput completion in Future.get method. And your WaitForUserInput.call method is waiting for the EDT to be available to execute a task. As I wrote above, you should not wait for anything inside EDT (in MainController.runSpecialCoding method). You should became accustomed to asynchronous programming, where you can't wait for action completion. One of the solutions is to use callbacks:



There are other approaches, but they are not well-suited for Java.

Most likely you should refactor your code that no "asynchronous code" requires UI interaction. Use "small" actions. When an action requires some user interaction, pass all intermediate data to a callback and consider job done. After user input start another action and pass user input and previous state to it as it's parameters.

I understand that your example is not a real-world application. With such a small "action" it's better to perform all the required interaction (confirmation) on EDT directly from MainController.runSpecialCoding method. And in a more complex scenario (real computations) there will be two tasks. One to run before user confirmation is required and one to run after the confirmation. Ah, there should be also some UI-related code in the callback, which displays a confirmation and starts a second task.

You cannot and should not create other EDT threads. And it is not a some special kind of thread. It is just a regular thread with some framework-specific code (swing/awt runnable). But that framework-specific code should be executed by only one thread because it is not "thread safe".

I don't think that change to "runnable" made this code working. Probably you had changed something else which was a real cause of the fix. As far as I remember, there is no much difference between runnable and callable in the executor. Runnable can be converted to a callable by a simple wrapper.

Anyway. Most important thing is to get an "asynchronous" mindset. You don't wait for anything on an EDT (don't do ft.get). You start it and just let in run. When code is completed, in notifies a "caller" about it's completion. Note that at this moment caller's method which launched a task is already complete. That callback analyzes data, updates UI and launches other asynchronous actions if needed. This is a good approach for swing (it keeps UI responsible). And sometime it is the only way to program UI (javascript is a good example).

Sidenote. This "callback" approach is very similar to a "continuation passing style" in functional languages. Instead of "running a task and waiting for result" you fires a task and tells it to "do that operation after task is complete".
Ted Jones
Greenhorn

Joined: Jan 30, 2014
Posts: 14
You are correct about the runnable. Once I did a .join() on the runnable it froze just like the rest. I completely understand what you are talking about now. It was a stretch for me. In what I've done in the past, you can run a sync process to main app and update the UI or whatnot. However, I need a hint on thinking in an async mind for JAVA. I programmed what you recommended, but I can't get through my brain how to apply it to my program.

The program I'm creating clicks on the screen and does multiple processes. I use it to do tasks that I do a lot, so I don't have to do them daily. They will be done when I wake up. So, the Threads I'm creating have to interact with the main screen and can possibly wait for user input. However, I want to be able to click on the main program and pause, stop or close and create a new thread so as I'm watching it I can change it if I see something. Right now, I have setup multiple threads to click multiple buttons and do different tasks.

So, I have a main class that has to accept GUI processes/inputs while I have GUI threads pointing and clicking the screen. It works now because I haven't wanted to look for a returned variable or error, but I want to take the program to the next level. I want the program to collect an error. Depending on the error, make a response. For example, if the screen is taking too long to load, I'm thinking about calling Robot and doing a screenshot. I can compare the screen shot with a saved loading error screen shot and compare them. If they are the same, I can ask the program to pause for a half an hour and try again. In all honestly, the program might manage itself and when all of the processes are done move to another and change the checkbox.

What I've been racking my brain over is it just a limitation with JAVA, or can I do something? As of right now, the only way I can see it in JAVA now is creating separate multiple programs and just have the first program manage the other java programs, or get rid of the idea that I can click on the main app to change what it is doing. However, that is all I can come up with.

Does anyone see another option?
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

I'd suggest reading the Concurrency in Swing tutorial (the whole Swing tutorial is really helpful, by the way). It will probably answer most of your questions.

I don't think you should need to run your tasks as separate processes, although that approach is possible and has some advantages. I also don't understand why handling errors is so problematic for you. Inside Java, you should get a neat exception for all kinds of errors. If you deal with external programs, it could be more complicated, depending on the exact behavior of the program in question. Taking screenshots looks a tad bit too complicated, though.

As for background threads waiting for user interaction, you need to design this carefully. Using SwingUtilities.invodeAndWait() would probably be a good start, in my opinion, but if there are several processes running in the background, all of them popping windows requiring user interaction, it could get messy. You might be better off designing some sort of a list (JTable?) with all running tasks and their states, and in this list indicate tasks needing user interaction. The user then might deal with the task in the order he likes, and won't get interrupted by other processes popping up their windows when he deals with a different one. At the same time, this would be a good place to manage the tasks as well. (Unfortunately, Java doesn't support pausing or terminating threads, so you'll have to build your own mechanism for that into your threads. You could safely terminate external process, though.) Obviously you'll need some kind of communications between the worker threads and your GUI, and it will be somewhat difficult, but definitely doable.
Maxim Karvonen
Ranch Hand

Joined: Jun 14, 2013
Posts: 103
    
  11
Ted Jones wrote:So, the Threads I'm creating have to interact with the main screen and can possibly wait for user input. However, I want to be able to click on the main program and pause, stop or close and create a new thread so as I'm watching it I can change it if I see something.

This will require some kind of interprocess (or inter-thread) communication. This is not specific to a swing. Your request (like pausing one of your processes) may come from a network, command line interface, etc... This request is received while your task is still running. So it is received on a non-task thread and you are forced to provide a way for the inter-process communication.

Ted Jones wrote:I want the program to collect an error. Depending on the error, make a response.

Can you clarify what a "collect an error" really means? Try to do this as specific as possible. You said that you have several processes. How are you going to collect results of several processes at the same time? Remember that these processes are running in parallel and may produce results in some unpredictable order.

If you need to "collect an error" from several threads, then spawn a new thread and do all waiting in it.
If you need to "collect an error" from only one process, why wait for it's completion on another thread? Just start a new thread and call a processor method. In terms of your first example it will be something like


In this example you don't block UI thread. You run a task on a separate thread and sometime "pokes" EDT to perform some action. Most likely you should create some Utility method to run queries in EDT (because there are no such methods in SwingUtilities). Something like


And then use it in the WaitForUserInput:


As you see, you still need to implement exception handling (and passing) in MySwingUtililites. It is definitely possible. And maybe you should use some locks to execute at most one action at the same time (I have never tested invokeLater with several modal dialogs).

Ted Jones wrote:What I've been racking my brain over is it just a limitation with JAVA, or can I do something? As of right now, the only way I can see it in JAVA now is creating separate multiple programs and just have the first program manage the other java programs, or get rid of the idea that I can click on the main app to change what it is doing.

You can manage other "programs". But because that programs are all running in parallel, you should introduce some "management protocol" for that tasks. They should discover new "requests" for them (by polling pending events at some times for example). Then you may send events or request to that processes. You may run a "master" thread and pass all events from it to an EDT using "invokeLater". But if you won't think carefully about "interprocess" communication, you may get a deadlock on that "master" thread.

At this point I didn't see clearly what exactly you are trying to do. You can "collect a result" whatever this means. Most likely you should not wait for this blocking all GUI and risking to get an "UI is unresponsive" problem. Better display some "process indicator" (indeterminate progress bar, for example), wait for result on other thread and only then update an UI. And this is even more true for "several processes". Do you really like to have non-responsive UI (and not able to control any processes at all) while waiting for result of one particular process?
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Callable Freezing Help