0

I am unable to update my UI even after wrapping all SWT code in "Display.getDefault().asyncExec".

Let's assume I have listener which is called clicking on one button.

Listener enterlisner = new Listener() {
     @Override
        public void handleEvent(Event event) 
        {
             Display.getDefault().asyncExec(new Runnable() 
             {
                 public void run() 
                 {
                    try 
                    {
                        if((event.keyCode == SWT.CR || event.keyCode == 13 || event.type == SWT.Selection) && btnAdd.isEnabled())
                        {
                            new ProgressMonitorDialog(shell).run(true, true, new IRunnableWithProgress() 
                            {
                                @Override
                                public void run(final IProgressMonitor monitor) throws InvocationTargetException,
                                        InterruptedException 
                                {

                                            // method1()

                                            // method2() {method2.1() , method2.2()}

                                            // method3() {method3.1() , method3.2()}

                                            // ....

                                            // ...

                                            // method10

                                }
                            });
                        }   
                    } 
                    catch (InvocationTargetException | InterruptedException e) 
                    {
                        e.printStackTrace();
                    }
                }
            });
        }
};

Could anyone please refer think link and let me know where I am wrong ?

How to bifurcate piece of methods that runs in a background thread ?

Community
  • 1
  • 1
  • You need to show us a minimal example of your code and the exact message you are getting. – greg-449 Aug 08 '16 at 06:41
  • Hi Greg. You can click on link above where I have written entire code – Rahul Prajapati Aug 08 '16 at 06:54
  • There is too much code there and it does not clearly say what the InvocationTargetException is. We need an [mcve]. But surrounding everything in asyncExec is almost certainly wrong. – greg-449 Aug 08 '16 at 06:58
  • This is actually a entire code which runs on my single click on button where I have methods & sub methods being called where I need to show progress bar. – Rahul Prajapati Aug 08 '16 at 07:24
  • 1
    Wrapping the whole code in asyncExec essentially achieves nothing. You must look at your code and identify each piece that runs in a background thread. Any access to UI operations in those places must use an asyncExec (or syncExec) call at that point. – greg-449 Aug 08 '16 at 07:29
  • An InvocationTargetException wraps an exception thrown by an invoked method or constructor. Giving us the exception type alone isn't enough. You need to give the full strack trace and full message. – nitind Aug 08 '16 at 07:34
  • Greg@ I have tried to minimize my code above. – Rahul Prajapati Aug 08 '16 at 12:59

1 Answers1

2

Wrapping the whole code in asyncExec when you are already in the UI thread essentially achieves nothing (except for some very specialized uses).

You must look at your code and identify each piece that runs in a background thread. Any access to UI operations in those places must use an asyncExec (or syncExec) call at that point.

The IRunnableWithProgress that you pass to ProgressMonitorDialog runs in a background thread. So each time you access any UI object in the IRunnableWithProgress code you must use a separate asyncExec or syncExec call.

So something like:

Listener enterlisner = new Listener() {
  @Override
  public void handleEvent(Event event) 
  {
    if ((event.keyCode == SWT.CR || event.keyCode == 13 || event.type == SWT.Selection) && btnAdd.isEnabled())
     {
       new ProgressMonitorDialog(shell).run(true, true, new IRunnableWithProgress() 
         {
           @Override
           public void run(final IProgressMonitor monitor) throws IvocationTargetException, InterruptedException 
           {
              ... code not using UI

              Display.getDefault().asyncExec(... code using UI ....);

              ... more code not using UI

              Display.getDefault().asyncExec(... more code using UI ....);
           }
         }
     }
  }
greg-449
  • 109,219
  • 232
  • 102
  • 145
  • But what if I have mix of code which updates UI & doesn't update UI ? Shall it be wrapped in multiple asyncExec() methods ? – Rahul Prajapati Aug 10 '16 at 05:53
  • Yes, multiple asyncExec or syncExec calls. Edited the example to show this – greg-449 Aug 10 '16 at 06:28
  • keeping Display.getDefault().asyncExec() out of "new ProgressMonitorDialog(shell)" show the progress moving but while keeping inside ProgressMonitorDialog() doesn't show – Rahul Prajapati Aug 10 '16 at 06:54
  • I don't understand what you mean by that. Note the `monitor.worked()` calls and other `IProgressMonitor` methods should not be put in an `asyncExec` call as they are designed to work in the background. – greg-449 Aug 10 '16 at 07:02