Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Standard Widget Toolkit (SWT) » Program with (a)syncExec() hangs after Thread.join()
Program with (a)syncExec() hangs after Thread.join() [message #451821] Wed, 09 March 2005 15:38 Go to next message
Robert is currently offline RobertFriend
Messages: 45
Registered: July 2009
Member
Hi!

I am working on a straightforward program for downloading files from the
web. I'd like to display a ProgressBar in the meantime. As soon as the
download completes, I want to continue working on the contents of the
file. So far so good, and the core of the program has been implemented and
seems to work. However, I can't figure out if the download has been
finished. I figured a Thread.join() would do the trick (wait for the
download thread to complete/die), but this causes my program to hang.
Without the join(), it works like a charm. I am obviously doing something
wrong with the threading (syncExec/asyncExec/join), but I don't understand
the problem.

Could anyone provide some insight?

Thanks!
Robert

My source code (simplified for sake of clarity):

----------------------------

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;

public class Testing {

public static void main ( String args[] ) {

final Display display = new Display();
Shell shell = new Shell(display);

final ProgressBar bar = new ProgressBar(shell, SWT.SMOOTH);
bar.setSize(400, 32);

final Button button = new Button(shell, SWT.PUSH);
button.setText("Go!");
button.setBounds(10, 60, 120, 28);
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected ( SelectionEvent event ) {
try {
bar.setMinimum(0);
bar.setMaximum(10000);
button.setEnabled(false);
Thread thread = new Thread() {
public void run ( ) {
final int[] completed = {0};
while ( true ) {
completed[0]++;
if ( completed[0] == 10000 ) break;
display.syncExec(new Runnable() {
public void run ( ) {
bar.setSelection(completed[0]);
}
});
}
}
};
thread.start();
//thread.join(); // <-- uncomment!
// want to continue here
} catch ( Exception e ) {
e.printStackTrace();
} finally {
button.setEnabled(true);
button.setText("Done!");
}
}
});

shell.setSize(640, 480);
shell.open();

while ( !shell.isDisposed() ) {
if ( !display.readAndDispatch() ) {
display.sleep();
}
}
display.dispose();
}
};
Re: Program with (a)syncExec() hangs after Thread.join() [message #451830 is a reply to message #451821] Wed, 09 March 2005 16:19 Go to previous messageGo to next message
Veronika Irvine is currently offline Veronika IrvineFriend
Messages: 1272
Registered: July 2009
Senior Member
Your thread.join is done from the UI thread (all widget events come in on
the UI thread). So effectively, you are saying that the UI thread should
stop (i.e. your GUI should hang) until the work done in your thread is
completed. And the work in your thread won't complete until it runs some
code in the UI thread. Deadlock. Suspending the UI thread defeats the
purpose of doing your work in another thread in the first place.

Why not just execute

button.setEnabled(true);
button.setText("Done!");

in the display.syncExec call from thread?

"Robert" <robert_x20032000@yahoo.com> wrote in message
news:d0n59k$8be$1@www.eclipse.org...
> Hi!
>
> I am working on a straightforward program for downloading files from the
> web. I'd like to display a ProgressBar in the meantime. As soon as the
> download completes, I want to continue working on the contents of the
> file. So far so good, and the core of the program has been implemented and
> seems to work. However, I can't figure out if the download has been
> finished. I figured a Thread.join() would do the trick (wait for the
> download thread to complete/die), but this causes my program to hang.
> Without the join(), it works like a charm. I am obviously doing something
> wrong with the threading (syncExec/asyncExec/join), but I don't understand
> the problem.
>
> Could anyone provide some insight?
>
> Thanks!
> Robert
>
> My source code (simplified for sake of clarity):
>
> ----------------------------
>
> import org.eclipse.swt.SWT;
> import org.eclipse.swt.events.SelectionAdapter;
> import org.eclipse.swt.events.SelectionEvent;
> import org.eclipse.swt.widgets.Button;
> import org.eclipse.swt.widgets.Display;
> import org.eclipse.swt.widgets.ProgressBar;
> import org.eclipse.swt.widgets.Shell;
>
> public class Testing {
>
> public static void main ( String args[] ) {
>
> final Display display = new Display();
> Shell shell = new Shell(display);
>
> final ProgressBar bar = new ProgressBar(shell, SWT.SMOOTH);
> bar.setSize(400, 32);
>
> final Button button = new Button(shell, SWT.PUSH);
> button.setText("Go!");
> button.setBounds(10, 60, 120, 28);
> button.addSelectionListener(new SelectionAdapter() {
> public void widgetSelected ( SelectionEvent event ) {
> try {
> bar.setMinimum(0);
> bar.setMaximum(10000);
> button.setEnabled(false);
> Thread thread = new Thread() {
> public void run ( ) {
> final int[] completed = {0};
> while ( true ) {
> completed[0]++;
> if ( completed[0] == 10000 ) break;
> display.syncExec(new Runnable() {
> public void run ( ) {
> bar.setSelection(completed[0]);
> }
> });
> }
> }
> };
> thread.start();
> //thread.join(); // <-- uncomment!
> // want to continue here
> } catch ( Exception e ) {
> e.printStackTrace();
> } finally {
> button.setEnabled(true);
> button.setText("Done!");
> }
> }
> });
>
> shell.setSize(640, 480);
> shell.open();
>
> while ( !shell.isDisposed() ) {
> if ( !display.readAndDispatch() ) {
> display.sleep();
> }
> }
> display.dispose();
> }
> };
>
Re: Program with (a)syncExec() hangs after Thread.join() [message #451838 is a reply to message #451830] Wed, 09 March 2005 16:39 Go to previous messageGo to next message
Robert is currently offline RobertFriend
Messages: 45
Registered: July 2009
Member
Thanks for your reply!

I had no idea I was suspending the UI thread; the cooperation between UIs
and threads are new to me. But when I think about it, it does makes
sense...

How would one normally find out if a threaded operation has completed? As
mentioned, I want to grab the contents of the downloaded file and continue
working on it -- in the original UI thread. But how do I detect whether or
not the download has been completed?

Thanks in advance!

Robert


Veronika Irvine wrote:

> Your thread.join is done from the UI thread (all widget events come in on
> the UI thread). So effectively, you are saying that the UI thread should
> stop (i.e. your GUI should hang) until the work done in your thread is
> completed. And the work in your thread won't complete until it runs some
> code in the UI thread. Deadlock. Suspending the UI thread defeats the
> purpose of doing your work in another thread in the first place.

> Why not just execute

> button.setEnabled(true);
> button.setText("Done!");

> in the display.syncExec call from thread?
Re: Program with (a)syncExec() hangs after Thread.join() [message #451854 is a reply to message #451821] Wed, 09 March 2005 17:24 Go to previous message
Stefan Zeiger is currently offline Stefan ZeigerFriend
Messages: 102
Registered: July 2009
Senior Member
Robert wrote:

You're creating and starting a background thread from the SWT event thread:

> button.addSelectionListener(new SelectionAdapter() {
> public void widgetSelected ( SelectionEvent event ) {
> try {
> bar.setMinimum(0);
> bar.setMaximum(10000);
> button.setEnabled(false);
> Thread thread = new Thread() {
> public void run ( ) {
> final int[] completed = {0};
> while ( true ) {
> completed[0]++;
> if ( completed[0] == 10000 ) break;

The background thread makes a synchronous callback to the event thread,
thus blocking your thread until the code has been executed on the event
thread:

> display.syncExec(new Runnable() {
> public void run ( ) {
> bar.setSelection(completed[0]);
> }
> });
> }
> }
> };
> thread.start();

....which will never happen because the event thread is blocked by a
join(), waiting for the thread that you started:

> //thread.join(); // <-- uncomment!

Voila, deadlocked.

You shouldn't join() on the background thread anyway. The whole purpose
of running your code in a background thead is to _not_ block the event
thread.

Instead call this:

> } finally {
> button.setEnabled(true);
> button.setText("Done!");

....from your background thread via asyncExec() after the other code in
the background thread has finished. And make sure you check for
button.isDisposed() before calling these methods on the button object
because it may have already been disposed (unless there's no way to
dispose it while your background thread is running).

--
Stefan Zeiger - Developer of Novocode Application Framework
Build SWT-based MVC GUIs via XML: http://www.novocode.com/naf/
Previous Topic:blue tab colour
Next Topic:FormLayout: width of Text and Combo differs
Goto Forum:
  


Current Time: Fri Apr 26 05:37:09 GMT 2024

Powered by FUDForum. Page generated in 0.03737 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top