3

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

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  ____|

这在下面的跟踪视图中很明显: 冻结线程的traceview

如果有帮助,我一直在使用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");
            }
        }
    }
}

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

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

4

2 回答 2

3

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

如果在 Surface 未准备好时(在 Callback.surfaceCreated 之前或 Callback.surfaceDestroyed 之后)重复调用它,您的调用将被限制为较慢的速率以避免消耗 CPU。

如果未返回 null,则此函数在内部保持锁定,直到相应的 unlockCanvasAndPost(Canvas) 调用,防止 SurfaceView 在绘制时创建、销毁或修改表面。这比直接访问 Surface 更方便,因为您不需要与 Callback.surfaceDestroyed 中的绘图线程进行特殊同步。

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

顺便提一句,

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

是多余的

于 2011-04-21T16:56:15.093 回答
3

从那以后,我发现了我的问题。我不知道为什么,但因为我不小心忘记了完全注释掉早期的 asyncTask(),因此有两个执行大致相同的任务,并且显然在使用相同的变量等时很难做到这一点。感谢您的指点,但我想这只是我的另一个粗心错误。

于 2011-04-22T15:00:57.730 回答