Android:线程间歇性暂停

时间:2011-04-18 18:36:11

标签: android multithreading android-canvas surfaceview trace

在我的应用程序中的随机点间歇性暂停的Thread(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 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");
            }
        }
    }
}

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

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

2 个答案:

答案 0 :(得分:3)

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

  

如果你反复打电话给   表面尚未准备好(之前   Callback.surfaceCreated或之后   Callback.surfaceDestroyed),你的电话   将被限制在一个缓慢的速度   为了避免消耗CPU。

     

如果未返回null,则此函数   内部持有锁,直到   相应   unlockCanvasAndPost(Canvas)调用,   阻止SurfaceView创建,   破坏或修改表面   正在被绘制。这可以   比访问更方便   直接表面,因为您不需要   与a做特殊同步   画线程   Callback.surfaceDestroyed。

我不确定CPU启动限制时的阈值是多少。刷新画布的线程数是多少?

btw,

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

是多余的

答案 1 :(得分:3)

我已经弄明白了我的问题。我不确定为什么,但因为我不小心忘记完全注释掉早期的asyncTask(),因此有两个人做了大致相同的任务,显然很难用相同的变量等来做。感谢您的指示,但我想这只是另一个不小心的错误。