Thursday 13 April 2017

SWT: syncExec Vs asyncExec

If you are working with SWT, you will come across the question in mind, what is the difference between syncExec and asyncExec, why do we require these methods etc., In this post, I am going to explain why do we require these methods and difference between syncExec, asyncExec with an example.

Why do we require syncExec and asyncExec methods?
SWT implements single threaded UI model. In this model, only the UI-thread can invoke UI operations. If you try and access an SWT object from outside the UI-thread, you get the exception "org.eclipse.swt.SWTException: Invalid thread access". So to allow other threads to perform operations on objects belonging to the UI-thread, SWT provides syncExec and asyncExec methods.

syncExec vs asyncExec
As I said, both syncExec and asyncExec methods are used to perform operations on objects belonging to UI thread. There is one difference between syncExec and asyncExec methods, the thread which calls syncExec method is suspended until the runnable completes. But in case of asyncExec mehtod, the caller of this method continues to run in parallel, and is not notified when the runnable has completed.

Let me clarify it with an example.

CustomDialog.java
package com.sample.ui;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class CustomDialog extends Dialog {

 public String name;
 private Text text1 = null;
 private Button button = null;

 public CustomDialog(Shell parentShell) {
  super(parentShell);
 }

 @Override
 protected void okPressed() {
  // Do operations if you want, when ok button pressed
  name = text1.getText();
  super.okPressed();
 }

 @Override
 protected Control createDialogArea(Composite parent) {
  Composite composite = (Composite) super.createDialogArea(parent);

  GridLayout gridLayout = new GridLayout();
  gridLayout.numColumns = 2;
  composite.setLayout(gridLayout);

  Label label1 = new Label(composite, SWT.NONE);
  label1.setText("Name:");
  text1 = new Text(composite, SWT.BORDER);

  button = new Button(composite, SWT.CHECK);
  button.setText("Have you been employed in the past six months?");

  GridData gridData1 = new GridData();

  gridData1.widthHint = 60;

  label1.setLayoutData(gridData1);

  GridData gridData4 = new GridData(GridData.FILL_HORIZONTAL);

  text1.setLayoutData(gridData4);

  GridData gridData7 = new GridData();
  gridData7.horizontalSpan = 2;
  button.setLayoutData(gridData7);

  return composite;
 }

 @Override
 protected void configureShell(Shell newShell) {
  super.configureShell(newShell);
  newShell.setText("My Custom Dialog");
 }

 @Override
 protected Point getInitialSize() {
  return new Point(450, 300);
 }

 @Override
 public String toString() {
  return "CustomDialog [name=" + name + "]";
 }

}


Test.java
package com.sample.ui;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.widgets.Display;

public class Test {

 public static void main(String[] args) {

  Display.getDefault().asyncExec(new Runnable() {

   public void run() {

    Dialog dialog = new CustomDialog(Display.getDefault().getActiveShell());
    dialog.open();
   }

  });

  System.out.println("I am done");
  stopExitingTheUiApplication();
 }

 /**
  * This stops the application from termination, when we use asyncExec method
  */
 private static void stopExitingTheUiApplication() {
  while (!Display.getDefault().isDisposed()) {
   if (!Display.getDefault().readAndDispatch()) {
    Display.getDefault().sleep();
   }
  }

 }
}

As you observe following snippet,
  Display.getDefault().asyncExec(new Runnable() {

   public void run() {

    Dialog dialog = new CustomDialog(Display.getDefault().getActiveShell());
    dialog.open();
   }

  });

  System.out.println("I am done");

I am opening the dialog in asyncExec method of Display class. So the dialog opens and the messages 'I am done' prints parallely.

Now replace the asyncExec method with syncExec method.


Test.java
package com.sample.ui;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.widgets.Display;

public class Test {

 public static void main(String[] args) {

  Display.getDefault().syncExec(new Runnable() {

   public void run() {

    Dialog dialog = new CustomDialog(Display.getDefault().getActiveShell());
    dialog.open();
   }

  });

  System.out.println("I am done");
  stopExitingTheUiApplication();
 }

 /**
  * This stops the application from termination, when we use asyncExec method
  */
 private static void stopExitingTheUiApplication() {
  while (!Display.getDefault().isDisposed()) {
   if (!Display.getDefault().readAndDispatch()) {
    Display.getDefault().sleep();
   }
  }

 }
}

You can able to see the output ‘I am done’, after you close the custom dialog






Previous                                                 Next                                                 Home

No comments:

Post a Comment