[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
|
[news.eclipse.platform.swt] Use case for Display.syncExec(Runnable runner) versus asyncExec
|
- From: Nik Bhattacharya <nik_bhat@xxxxxxxxx>
- Date: Mon, 23 Oct 2006 18:46:41 -0500
- Newsgroups: eclipse.platform.swt
- Organization: EclipseCorner
- User-agent: Thunderbird 1.5.0.7 (Windows/20060909)
I am trying to figure out what is appropriate usage of the syncExec
method on Display. If syncExec is what I understand it to be, then it
basically will not return until after the runnable method has executed.
Take for example the following code (see snippet below for a fully
functional example. Run with swt.jar on classpath)
private void executeAsynchronously(Runnable runnable) {
captureMethodEnteredTime();
display.asyncExec(runnable);
captureMethodExitedTime();
}
private void executeSynchronously(Runnable runnable) {
captureMethodEnteredTime();
display.syncExec(runnable);
captureMethodExitedTime();
}
private void captureMethodExitedTime() {
endTime = System.currentTimeMillis();
returnedAt.setText("Returned At : " + endTime + "(" + (endTime -
startTime) + ") ms");
}
private void captureMethodEnteredTime() {
startTime = System.currentTimeMillis();
enteredAt.setText("Entered At : " + startTime);
}
Say that the runnable takes 10 seconds to execute, then in the case of
the executeSynchronously method, the captureMethodExitedTime() should
print out not earlier than 10 seconds after the syncExec was called. In
the case of the asyncExec the captureMethodExitedTime() should print out
almost immediately.
In which situations should we wait and in which should we do an async
process? In either case, it seems like if the runnable is an inner
class, it can update the UI with appropriate messages as needed.
I have included my sample code below. Interesting to see how the UI
locks up when a long running runnable is processed versus if you spawn
another thread to do the work in the runnable that keeps the UI
responsive.
Thanks in advance,
Nik
//complete code below. Need swt.jar on classpath to execute
package com.nikb.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
/**
* Shows the difference between synch and asych execution.
*
* @author Nbhattacharya
*
*/
public class AsyncVersusSyncWindow {
private Text text;
private Display display;
private Text finalOutput;
private Button createSimpleRunnableButton;
private Button createThreadedRunnable;
private Text returnedAt;
private Text enteredAt;
private Button goButton;
private Button syncExecButton;
private Button asyncExecButton;
private Label methodEnteredAt;
private Label methodReturnedAt;
public long startTime;
private long endTime;
protected boolean cancel;
private static int count = 0;
public AsyncVersusSyncWindow(){
initialize();
}
private void initialize() {
display = new Display();
Shell asyncVersusSynchShell = new Shell(display);
asyncVersusSynchShell.setText("Async Versus Synch Tester");
final GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 2;
asyncVersusSynchShell.setLayout(gridLayout);
asyncVersusSynchShell.setBounds(200, 200, 595, 386);
new Label(asyncVersusSynchShell, SWT.NONE);
final Group optionsGroup = new Group(asyncVersusSynchShell, SWT.NONE);
optionsGroup.setText("Options");
optionsGroup.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false,
false, 2, 1));
final GridLayout gridLayout_2 = new GridLayout();
optionsGroup.setLayout(gridLayout_2);
syncExecButton = new Button(optionsGroup, SWT.RADIO);
syncExecButton.setText("Sync Exec");
syncExecButton.setSelection(true);
asyncExecButton = new Button(optionsGroup, SWT.RADIO);
asyncExecButton.setText("Async Exec");
final Group runnableTypeGroup = new Group(optionsGroup, SWT.NONE);
runnableTypeGroup.setText("Runnable Type");
runnableTypeGroup.setLayoutData(new GridData());
runnableTypeGroup.setLayout(new GridLayout());
createSimpleRunnableButton = new Button(runnableTypeGroup, SWT.RADIO);
createSimpleRunnableButton.setText("Create simple runnable");
createThreadedRunnable = new Button(runnableTypeGroup, SWT.RADIO);
createThreadedRunnable.setLayoutData(new GridData());
createThreadedRunnable.setText("Create runnable that spawns another
thread");
createThreadedRunnable.setSelection(true);
goButton = new Button(asyncVersusSynchShell, SWT.NONE);
goButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(final SelectionEvent e) {
doRunProcess();
}
});
goButton.setLayoutData(new GridData());
goButton.setText("Go!");
final Button cancelButton = new Button(asyncVersusSynchShell, SWT.NONE);
cancelButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(final SelectionEvent e) {
cancel = true;
}
});
cancelButton.setText("Cancel");
methodEnteredAt = new Label(asyncVersusSynchShell, SWT.NONE);
methodEnteredAt.setText("Method Entered At:");
enteredAt = new Text(asyncVersusSynchShell, SWT.BORDER);
enteredAt.setEnabled(false);
enteredAt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
methodReturnedAt = new Label(asyncVersusSynchShell, SWT.NONE);
methodReturnedAt.setText("Method Returned At:");
returnedAt = new Text(asyncVersusSynchShell, SWT.BORDER);
returnedAt.setEnabled(false);
returnedAt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
final Label label = new Label(asyncVersusSynchShell, SWT.SEPARATOR |
SWT.HORIZONTAL);
label.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false,
2, 1));
new Label(asyncVersusSynchShell, SWT.NONE);
finalOutput = new Text(asyncVersusSynchShell, SWT.BORDER);
finalOutput.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
false));
final Group additionalGroup = new Group(asyncVersusSynchShell, SWT.NONE);
additionalGroup.setText("Additional");
final GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false,
false, 2, 1);
gridData.widthHint = 575;
additionalGroup.setLayoutData(gridData);
final GridLayout gridLayout_1 = new GridLayout();
gridLayout_1.numColumns = 2;
additionalGroup.setLayout(gridLayout_1);
final Button testResponsivenessButton = new Button(additionalGroup,
SWT.NONE);
testResponsivenessButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(final SelectionEvent e) {
text.setText(text.getText().concat(" Yes!"));
}
});
testResponsivenessButton.setText("Test Responsiveness");
text = new Text(additionalGroup, SWT.BORDER);
text.setLayoutData(new GridData());
final Button clearFieldsButton = new Button(additionalGroup, SWT.NONE);
clearFieldsButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(final SelectionEvent e) {
clearFields();
}
});
clearFieldsButton.setText("Clear Fields");
new Label(additionalGroup, SWT.NONE);
asyncVersusSynchShell.open();
while(!asyncVersusSynchShell.isDisposed()){
if(!display.readAndDispatch()){
display.sleep();
}
}
display.dispose();
}
protected void doRunProcess() {
clearFields();
if(syncExecButton.getSelection()){
executeSynchronously(getRunnableProcess("SYNC"));
} else {
executeAsynchronously(getRunnableProcess("ASYNC"));
}
}
private Runnable getRunnableProcess(String type) {
if(createSimpleRunnableButton.getSelection()){
System.out.println("simple");
return new LongSimpleRunnable(type);
} else {
System.out.println("threaded");
return new LongRunnableWithInternalThread(type);
}
}
private void clearFields() {
cancel = false;
text.setText("");
enteredAt.setText("");
returnedAt.setText("");
finalOutput.setText("");
}
private void executeAsynchronously(Runnable runnable) {
captureMethodEnteredTime();
display.asyncExec(runnable);
captureMethodExitedTime();
}
private void executeSynchronously(Runnable runnable) {
captureMethodEnteredTime();
display.syncExec(runnable);
captureMethodExitedTime();
}
private void captureMethodExitedTime() {
endTime = System.currentTimeMillis();
returnedAt.setText("Returned At : " + endTime + "(" + (endTime -
startTime) + ") ms");
}
private void captureMethodEnteredTime() {
startTime = System.currentTimeMillis();
enteredAt.setText("Entered At : " + startTime);
}
public static void main(String[] args) {
AsyncVersusSyncWindow window = new AsyncVersusSyncWindow();
}
/**
* Spawns a thread in the run method and calls display.asyncExec to
update the ui.
* The UI is not locked up.
*
* @author Nbhattacharya
*
*/
class LongRunnableWithInternalThread implements Runnable {
private String name;
private boolean wasCancelled;
public LongRunnableWithInternalThread(String name) {
this.name = name + " SPAWN NEW THREAD " + count++;
}
public void run() {
Thread oneThread = new Thread(){
public void run() {
final long start = System.currentTimeMillis();
display.asyncExec(new Runnable(){
public void run() {
finalOutput.setText("Running (" + name + ")..." + start); //this
should throw an exception
}
});
for (int i = 0; i < 5; i++) {
if(!cancel){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
wasCancelled = true;
break;
}
}
final long end = System.currentTimeMillis();
display.asyncExec(new Runnable() {
public void run() {
finalOutput.setText(name + " " + (wasCancelled ? "cancelled" :
"done") + " at" + end + "(" + (end - start) + ") ms");
}
});
}
};
oneThread.start();
}
}
/**
* A long runnning process in the run method. The UI locks up when the
run is executed.
*
* @author Nbhattacharya
*
*/
class LongSimpleRunnable implements Runnable {
private String name;
public LongSimpleRunnable(String name) {
this.name = name + " SIMPLE RUNNABLE " + count++;
}
public void run() {
long start = System.currentTimeMillis();
finalOutput.setText("Running (" + name + ")..." + start); //this
should throw an exception
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
finalOutput.setText(name + " done at" + end + "(" + (end - start)+ ")
ms");
}
}
}