Android 当GLThread非常忙且应用程序处于后台时获取ANR

Android 当GLThread非常忙且应用程序处于后台时获取ANR,android,opengl-es,background,android-anr-dialog,Android,Opengl Es,Background,Android Anr Dialog,当我的GLThread正在做一项密集的工作时,我注意到了以下奇怪的行为 启动应用程序并等待GLThread执行密集任务。 将应用程序发送到后台 从firebase发送推送通知 等待ANR出现(因为应用程序无法唤醒通知服务) 如果不是将应用程序发送到后台,而是让应用程序在前台等待,则通知将到达,并且ANR不会显示 理论上,GLThread不是主线程,所以我应该能够在那里做任何类型的工作,而不需要ANR 您可以在此处找到我的项目: 为了重现我的“密集工作”,我在onDrawFrame函数上放了一个

当我的GLThread正在做一项密集的工作时,我注意到了以下奇怪的行为

启动应用程序并等待GLThread执行密集任务。 将应用程序发送到后台 从firebase发送推送通知 等待ANR出现(因为应用程序无法唤醒通知服务)

如果不是将应用程序发送到后台,而是让应用程序在前台等待,则通知将到达,并且ANR不会显示

理论上,GLThread不是主线程,所以我应该能够在那里做任何类型的工作,而不需要ANR

您可以在此处找到我的项目:

为了重现我的“密集工作”,我在onDrawFrame函数上放了一个无限循环

public void onDrawFrame(GL10 gl) {
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    while(true)
    {
        Log.e("GLThread", "draw");
    }
}

任何帮助都将不胜感激。

问题在于这个无限循环是onDrawFrame()回调,通过这样的操作您将锁定GL线程

我想GL线程是来自GLSURFACHEVIEW还是类似的?你必须明白,你不能在这个方法中放置一个无限循环。onDrawFrame()函数只是每次曲面准备绘制新帧时由GL线程触发的回调。如果不允许回调继续,则将阻止GL线程


因此,除了不允许工作流继续之外,与GL线程通信的其他线程也将被锁定。例如,当UI线程告诉GLSurface停止时,在这种情况下会导致ANR,因为onDrawFrame()方法由于无限循环而持有当前GL同步锁。

为了重现我的“密集工作”,我只在onDrawFrame函数上放了一个无限循环。问题是,即使使用无限循环,当de应用程序在前台时,我也会收到通知,但当它在后台时,我不会收到通知。您的onDrawFrame是否来自GLSurfaceView?请检查这个类的源代码。在这个方法中放置一个无限循环不会模拟密集的工作,相反会导致更多的问题,因为这个回调在一个同步块中,并且每当UI尝试与surface通信时,应用程序都会得到一个ANR。如果没有循环,您也会得到一个ANR,那么请发布您在onDrawFrame方法中执行的真实源代码,以便更好地理解问题。ANR仅在应用程序位于后台并且我发送推送通知时显示。我无法发布代码,因为它执行了很多操作,并且我提供了一个显示错误的最小项目。请检查GLSurfaceView源代码。onDrawFrame是GL线程循环中的回调,其中包含一个使用sGLThreadManager作为围栏的同步块。此围栏还用于GLSURFACHEVIEW.onPause等方法以及与GL线程通信的其他UI方法。这意味着,如果触发了一个surface UI方法,当尝试通知GL线程时,如果sGLThreadManager被永久锁定(例如无限循环),则会生成一个ANR,该任务不会将控制权返回GL线程循环,或者是一项需要很长时间才能完成的任务。在推送通知中发生这种情况有点奇怪。但是,如果主线程仍在曲面的一个同步块中等待,则可能会产生此错误,因为GL线程持有锁,原因如上所述。然后,与主线程的任何交互都将产生一个ANR。