Android:线程间歇性暂停

发布于 2024-11-02 03:36:13 字数 2919 浏览 0 评论 0原文

线程(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 freeze 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); 我在此调用之前和之后插入了一条日志,并且在应用程序冻结后不会记录之后的日志;但之前的日志是该线程上最后记录的事件。它也没有暂停或使用空画布,因为我也为这些实例添加了日志;在应用程序完成之前,它们甚至不会被记录一次。

having some trouble with a Thread (CanvasThread) that is intermittently pausing at random points within my application. Everything else in the app continues to function as necessary, it's simply this thread that randomly blocks out for some reason and doesn't draw anything new to the screen. I noticed that Surface.lockCanvasNative() seems to be the last function called before the block, and the first one returned after. In a pattern as such:

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

This is evident with the traceview below:
traceview of frozen thread

I have been using the CanvasThread.run() below if it helps:

@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");
            }
        }
    }
}

Just let me know if I can provide any other useful information. I'm simply looking for clues as to why my thread might be blocking at this point? Thanks for any help in advance!

I've since narrowed the block down to mSurfaceHolder.unlockCanvasAndPost(canvas); I inserted a log before and after this call and the one after is not logged after app is frozen; but the log before is last logged event on this thread. It's not pausing or using a null canvas either, because I threw in logs for those instances as well; which are not logged even once until app is done.

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

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

发布评论

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

评论(2

盛装女皇 2024-11-09 03:36:13

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

如果您在
Surface 尚未准备好(之前
Callback.surfaceCreated 或之后
Callback.surfaceDestroyed),你的电话
将被限制为较慢的速率
以避免消耗CPU。

如果没有返回null,则该函数
内部持有锁,直到
相应的
调用unlockCanvasAndPost(Canvas),
阻止 SurfaceView 创建,
破坏或修改表面
当它被绘制时。这可以是
比访问更方便
直接表面,因为您不需要
进行特殊同步
拉入螺纹
Callback.surfaceDestroyed。

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

顺便说一句,

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

是多余的

I'm not sure if this could be the reason, but under SurfaceHolder.lockCanvas(), it warns that,

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.

I'm not sure what the threshold is when the CPU starts throttling. How many threads are refreshing the canvas?

btw,

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

is redundant

烟织青萝梦 2024-11-09 03:36:13

从那以后我已经弄清楚了我的问题。我不知道为什么,但因为我不小心忘记完全注释掉之前的 asyncTask(),因此有两个执行大致相同的任务,并且显然很难使用相同的变量等来执行此操作。感谢您的指点,但我想这只是我的另一个粗心错误。

I have since figured out my problem. I'm not sure why but because I had accidentally forgot to fully comment out an earlier asyncTask(), thus had two doing roughly the same tasks and obviously struggling to do so with the same variables and such. Thanks for your pointers, but simply another careless mistake on my part I guess.

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