Wednesday, May 21, 2008

InvokeAndBlock, Foxtrot Inspired Threading In LWUIT

I previously mentioned that LWUIT has some nifty threading tools inspired by Foxtrot but didn't get into details, this is made worse by the fact that even people coming from Swing don't know enough about Foxtrot. So here I'll try to explain the basic concepts behind this threading approach which many consider superior to the simple approach in MIDP/Swing, but first we have to understand modal dialogs.

When people talk about dialog modality they often mean two separate things, the first indicates that the dialog intercepts all input and blocks the background form/window which is the true definition of modality. However, there is another aspect often associated with modality that is really important from a programmers perspective and simplified our code considerably:
public void actionPerformed(ActionEvent ev) {
// will return true if the user clicks "OK"
if(!Dialog.show("Question", "How Are You", "OK", "Not OK")) {
// ask what went wrong...
}
}
Notice that the dialog show method will block the calling thread until the user clicks OK or Not OK...
If you read a bit about LWUIT you would notice that we are blocking the EDT (Event Dispatch Thread) which is also responsible for painting, how does the dialog paint itself or handle events?

The secret is invokeAndBlock, it allows us to "block" the EDT and resume it while keeping a "nested" EDT functioning. The semantics of this logic are a bit hairy so I won't try to explain them further, this functionality is also available in Swing which has the exact same modality feature however Swing doesn't expose the "engine" to developers. Foxtrot, exposes this undocumented engine to Swing developers, in LWUIT we chose to expose the ability to block the EDT (without "really" blocking it) as a simple API: invokeAndBlock.

The best way to explain this is by example:
public void actionPerformed(ActionEvent ev) {
label.setText("Initiating IO, please wait...");
Display.getInstance().invokeAndBlock(new Runnable() {
public void run() {
// perform IO operation...
}
});
label.setText("IO completed!");
// update UI...
}

Notice that the behavior here is similar to the modal dialog, invokeAndBlock "blocked" the current thread despite the fact that it is the EDT and performed the run() method in a separate thread. When run() completes the EDT is resumed. All the while repaints and events occur as usual, you can have invokeAndBlock calls occurring while another invokeAndBlock is still pending there are no limitations here.

As you can see this is a very simple approach for thread programming in UI, you don't need to block your flow and track the UI thread. You can just program in a way that seems sequential (top to bottom) but really uses multi-threading correctly without blocking the EDT.

No comments:

Post a Comment