Android:线程间歇性暂停

标签 android multithreading android-canvas surfaceview trace

在我的应用程序中间歇性地在随机点暂停的线程 (CanvasThread) 遇到一些问题。应用程序中的所有其他内容都会根据需要继续运行,只是这个线程出于某种原因随机阻塞并且不会在屏幕上绘制任何新内容。我注意到 Surface.lockCanvasNative() 似乎是 block 之前调用的最后一个函数,并且是之后返回的第一个函数。在这样的模式中:

Surface.lockCanvasNative (Landroid/graphics/Rect)Landroid/graphics/Canvas; @ 26,560 msec  ____
Surface.lockCanvasNative (Landroid/graphics/Rect)Landroid/graphics/Canvas; @ 40,471 msec  ____|

Surface.lockCanvasNative (Landroid/graphics/Rect)Landroid/graphics/Canvas; @ 40,629 msec  ____
Surface.lockCanvasNative (Landroid/graphics/Rect)Landroid/graphics/Canvas; @ 54,516 msec  ____|

下面的跟踪 View 很明显: traceview of frozen thread

如果有帮助,我一直在使用下面的 CanvasThread.run():

@Override
public void run() {

    boolean tellRendererSurfaceChanged = true;

    /*
     * This is our main activity thread's loop, we go until
     * asked to quit.
     */
    while (!mDone) {
        /*
         *  Update the asynchronous state (window size)
         */
        int w;
        int h;
        synchronized (this) {
            // If the user has set a runnable to run in this thread,
            // execute it and record the amount of time it takes to 
            // run.
            if (mEvent != null) {
                mEvent.run();
            }

            if(needToWait()) {
                while (needToWait()) {
                    try {
                        wait();
                    } catch (InterruptedException e) {

                    }
                }
            }
            if (mDone) {
                break;
            }
            tellRendererSurfaceChanged = mSizeChanged;
            w = mWidth;
            h = mHeight;
            mSizeChanged = false;
        }


        if (tellRendererSurfaceChanged) {
            mRenderer.sizeChanged(w, h);
            tellRendererSurfaceChanged = false;
        }

        if ((w > 0) && (h > 0)) {
            // Get ready to draw.
            // We record both lockCanvas() and unlockCanvasAndPost()
            // as part of "page flip" time because either may block
            // until the previous frame is complete.

            Canvas canvas = mSurfaceHolder.lockCanvas();

            if (canvas != null) {
                // Draw a frame!
                mRenderer.drawFrame(canvas);                        
                mSurfaceHolder.unlockCanvasAndPost(canvas);

                //CanvasTestActivity._isAsyncGoTime = true;    
            }
            else{
                Log.v("CanvasSurfaceView.CanvasThread", "canvas == null");
            }
        }
    }
}

如果我能提供任何其他有用的信息,请告诉我。我只是在寻找关于为什么我的线程此时可能会阻塞的线索?提前感谢您的帮助!

我已经将 block 缩小到 mSurfaceHolder.unlockCanvasAndPost(canvas); 我在这个调用之前和之后插入了一个日志,并且在应用程序卡住后不记录之后的日志;但之前的日志是该线程上最后记录的事件。它也没有暂停或使用空 Canvas ,因为我也为这些实例输入了日志;在应用程序完成之前甚至不会记录一次。

最佳答案

我不确定这是否是原因,但在 SurfaceHolder.lockCanvas() 下,它警告说,

If you call this repeatedly when the Surface is not ready (before Callback.surfaceCreated or after Callback.surfaceDestroyed), your calls will be throttled to a slow rate in order to avoid consuming CPU.

If null is not returned, this function internally holds a lock until the corresponding unlockCanvasAndPost(Canvas) call, preventing SurfaceView from creating, destroying, or modifying the surface while it is being drawn. This can be more convenient than accessing the Surface directly, as you do not need to do special synchronization with a drawing thread in Callback.surfaceDestroyed.

我不确定 CPU 开始节流时的阈值是多少。有多少线程正在刷新 Canvas ?

顺便说一句,

if(needToWait()) {
                while (needToWait()) {

是多余的

关于Android:线程间歇性暂停,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5707303/

相关文章:

java - 如何将变量传递给新的 Runnable 声明?

java - 解析Android - 如何从另一个类查询ObjectId到_User类

android - 如何使用库 Zbar 使扫描条码的区域更小 android

java - Selector.select 没有按预期阻塞

android - 在 Picasso 设置的 ImageView 上画一条线

android - 试图将图像从矩形形状转换为圆形

android canvas - 我可以有多种绘制方法吗?

android - Flutter 中的 WhatsApp 来电通知

c - Windows 套接字似乎是非双工的

ruby-on-rails - 如何在我的 Rails 线程池中实现 "join"?