简体   繁体   中英

Java Application is not responding after using Thread.Sleep();

I am currently having some trouble when running the follwing code. If I delete this part the problems disappear so this part of my whole code has to be the problem. It runs and draws what I want perfectly but after a few seconds (maxAddedRuntime is set via user (milliseconds)) the application freezes for a while (window is not responding Windows message) and starts over with drawing after waiting approximately the same time while the window is frozen. What do I do wrong? I am using SWT and a canvas to draw. Thank you for your help

public void drawNetwork(Canvas canvas, GC gc, Network network, Shell shlNetworkVisualizer) {        
    startTime = System.currentTimeMillis();
    endTime = startTime + maxAddedRuntime;
    this.drawNetworkAlg1(canvas, gc, network);
    int canvasHeight = canvas.getBounds().height;
    int canvasWidth = canvas.getBounds().width;
    while (System.currentTimeMillis()<endTime) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }   
        gc.fillRectangle(0, 0, canvasWidth, canvasHeight); //ClearCanvas basically
        for (Nodek: network.node) {
            //drawSomeStuff
        }
        for (Edge k: network.edges) {
            //alsoDrawSomeStuff
        }       
    }
}   

An SWT app must return to the main Display.readAndDispatch loop as quickly as possible. So you cannot use a loop with a Thread.sleep call - this will just lock up the UI until the loop ends.

Instead you can use Display.timerExec to run code after a delay. You would use this to run a single step (just one gc.fillRectange for example) and then call Display.timerExec again to schedule the next step.

public void timerExec(int milliseconds, Runnable runnable)

Note: The GC you receive from a paint event is only valid during the paint. The timerExec call should normally just call redraw on the canvas to cause a new paint event to be generated.

Here is a simple class that does basic timerExec calls and paints:

class Progress
{
  private final Canvas canvas;
  private final long endTime;

  Progress(Canvas c)
  {
    canvas = c;

    endTime = System.currentTimeMillis() + 1_000;

    canvas.addListener(SWT.Paint, this::paint);

    canvas.getDisplay().timerExec(100, this::timer);
  }

  private void paint(Event event)
  {
    GC gc = event.gc;

    int canvasHeight = canvas.getBounds().height;
    int canvasWidth = canvas.getBounds().width;

    gc.fillRectangle(0, 0, canvasWidth, canvasHeight);

    // TODO more painting
  }


  private void timer()
  {
    if (canvas.isDisposed()) {  // Don't continue if control closed
      return;
    }

    canvas.redraw();

    if (System.currentTimeMillis() < endTime) {
      canvas.getDisplay().timerExec(100, this::timer);
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM