“线程已经启动”当恢复活动时

发布于 2024-09-07 06:12:13 字数 789 浏览 3 评论 0原文

这是我的情况: 我正在为 Android 构建一个游戏,我的游戏活动由自定义 SurfaceView 组成,它具有用于游戏逻辑和渲染的线程。该架构类似于 Google 网站上的 LunarLander 演示。

当 Activity 启动时,它会创建 SurfaceView 并调用此方法:

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {   
        renderThread.start();
    }

当我按主页按钮退出游戏时,会调用 onPause() 方法,该方法会调用 SurfaceDestroyed()。在 surfaceDestroyed 中,我通过调用以下命令来停止游戏线程:

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        synchronized(holder)
        {
            renderThread.stop();
        }
    }       

应用程序正常进入后台。然后,当我通过按图标重新启动应用程序时,我会在日志中收到“线程已启动”消息以及屏幕上的“强制关闭”弹出窗口。当活动在渲染线程上调用 start() 时进入“surfaceCreated”方法时,会出现此消息。

现在我已经研究了几个小时,但不明白这是为什么。我相信当我关闭应用程序时我的线程会停止,所以我不明白为什么它说它已经启动。

Here is my situation:
I am building a game for android and my game's activity is composed of a custom surfaceView which has a thread for the game logic and rendering. The architecture is similar to the LunarLander demo from Google's website.

When the activity starts it creates the surfaceView and calls this method:

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {   
        renderThread.start();
    }

When I press the home button to exit the game, the onPause() method is called, which calls surfaceDestroyed(). In surfaceDestroyed I stop the game Thread by calling:

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        synchronized(holder)
        {
            renderThread.stop();
        }
    }       

The app goes to background fine. Then, when I relaunch the app by pressing the icon, I get a "Thread already started" message in the log along with a "force close" popup on the screen. This message happens when the activity enters the "surfaceCreated" method when it calls start() on the render thread.

Now I've looked into it for hours and can't figure out why this is. I believe my thread is stopped when I close the app so I don't understand why it says it has already started.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

心如狂蝶 2024-09-14 06:12:13

这些方法的作用并不如您想象的那样。来自 API 文档

启动线程永远是不合法的
不止一次。

和:

public final void stop() - 已弃用。这种方法本质上是不安全的。

如果要暂停线程,则必须在线程内使用 Object.wait()Objecft.notifyAll()

Those methods don't do what you think they do. From the API doc:

It is never legal to start a thread
more than once.

And:

public final void stop() - Deprecated. This method is inherently unsafe.

If you want to pause a thread, you have to use Object.wait() and Objecft.notifyAll() from within the thread.

时光匆匆的小流年 2024-09-14 06:12:13

在我看来,如果您打算经常启动和停止线程,则不应将代码打包到 Thread 的子类中(示例中这样做是因为它使代码更短)。请改用 Runnable。这样,您可以在需要时停止并丢弃旧的 Thread,并在需要再次启动时创建一个新的 Thread 对象来执行 Runnable。

private TutorialRunnable tutorialRunnable;

...

// Synchronization and error checking omitted for brevity.
public void surfaceCreated(SurfaceHolder holder) {
    thread = new Thread(tutorialRunnable);
    thread.start();
}

public void surfaceDestroyed(SurfaceHolder holder) {
    tutorialRunnable.setRunning(false);
    while (thread != null) {
        try {
            thread.join();
            thread = null;
        } catch (InterruptedException e) {
        }
    }
}

此外,依赖异常也是一种不好的形式。当您自己的代码出现意外行为时,这应该作为最后的手段。

In my opinion you should not pack your code into a subclass of Thread if you intend to be starting and stopping the Thread often (the examples do it because it makes the code shorter). Use a Runnable instead. That way you can stop and discard the old Thread when you want and create a new Thread object to execute the Runnable when you need to start it again.

private TutorialRunnable tutorialRunnable;

...

// Synchronization and error checking omitted for brevity.
public void surfaceCreated(SurfaceHolder holder) {
    thread = new Thread(tutorialRunnable);
    thread.start();
}

public void surfaceDestroyed(SurfaceHolder holder) {
    tutorialRunnable.setRunning(false);
    while (thread != null) {
        try {
            thread.join();
            thread = null;
        } catch (InterruptedException e) {
        }
    }
}

Also, relying on exceptions is bad form. That should be used as a last resort when your own code behaves unexpectedly.

余生共白头 2024-09-14 06:12:13

一个糟糕的解决方案,但它有效......

 public void surfaceCreated(SurfaceHolder holder) {
        try{
        _thread.setRunning(true);
        _thread.start();
        }catch(Exception ex){
            _thread = new TutorialThread(getHolder(), this);
            _thread.start();
        }

    }

热烈欢迎更正。

A bad solution but it works..

 public void surfaceCreated(SurfaceHolder holder) {
        try{
        _thread.setRunning(true);
        _thread.start();
        }catch(Exception ex){
            _thread = new TutorialThread(getHolder(), this);
            _thread.start();
        }

    }

corrections are warmly welcomed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文