Java应用程序在使用Thread.Sleep()后未响应。

huangapple go评论62阅读模式
英文:

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

问题

我目前运行以下代码时遇到了一些问题。如果我删除这部分,问题就消失了,所以我整个代码中的这部分肯定有问题。它能够正常运行并绘制我想要的内容,但是在几秒钟后(maxAddedRuntime由用户设置(毫秒)),应用程序会冻结一段时间(窗口显示未响应的消息),然后在窗口冻结的同时等待大约相同的时间后重新开始绘制。我做错了什么?

我正在使用SWT和一个画布来进行绘制。谢谢您的帮助。

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); //清除画布
        for (Node node : network.node) {
            //绘制一些内容
        }
        for (Edge edge : network.edges) {
            //也可以绘制一些内容
        }
    }
}
英文:

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()&lt;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
		}		
	}
}	

答案1

得分: 3

一个 SWT 应用程序必须尽快返回主 Display.readAndDispatch 循环。因此,您不能使用带有 Thread.sleep 调用的循环 - 这只会在循环结束之前锁定 UI。

相反,您可以使用 Display.timerExec 在延迟后运行代码。您可以使用它来运行单个步骤(例如,只运行一个 gc.fillRectange),然后再次调用 Display.timerExec 来安排下一步。

public void timerExec(int milliseconds, Runnable runnable)

注意:从绘制事件中获取的 GC 仅在绘制期间有效。timerExec 调用通常应该只在画布上调用 redraw,以触发生成新的绘制事件。

这是一个执行基本的 timerExec 调用并进行绘制的简单类:

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 更多绘制
  }


  private void timer()
  {
    if (canvas.isDisposed()) {  // 如果控件已关闭,则不要继续
      return;
    }

    canvas.redraw();

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

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&#39;t continue if control closed
      return;
    }

    canvas.redraw();

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

huangapple
  • 本文由 发表于 2020年10月20日 02:55:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/64433534.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定