Android SurfaceView / MultiThreading乱搞,线程陷入“信号捕手循环”

时间:2016-08-15 00:11:21

标签: java android multithreading

我一直在为Android开发一种游戏引擎,但我有一些严重的稳定性问题。

我使用SurfaceView和已实现的Runnable进行多线程处理,以获得我的主/ UI线程的一些工作。该类的简化版如下所示:

private class MenuView extends SurfaceView implements Runnable
{
    Thread T = null;
    SurfaceHolder holder;
    Canvas c;
    boolean run;

    public MenuView(Context context) {
        super(context);
        holder = getHolder();
    }

    @Override
    public void run() {
        while(run)
        {
            if(!holder.getSurface().isValid())
            {
                continue;
            }
            c = holder.lockCanvas();

    //Doing updates and drawing stuff

            holder.unlockCanvasAndPost(c);
        }
    }


    public void pause()
    {
        run = false;
        try
        {
            T.join();
        }
        catch (InterruptedException e)
        {
            Log.e("Error:", "joining thread failed!");
        }
    }

    public void resume()
    {
        run = true;
        T = new Thread(this);
        T.start();
    }

    //bunch of helper methods with no effect on this problem :(

}

正如你所看到的,我的“Worker”线程被一个由“run”boolean控制的无限while循环捕获,并且这个boolean是使用onPause()中调用的pause()和resume()方法设置的我的活动的onResume()方法如下所示:

MenuView menuV;
Random Rand = new Random();

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    Screen = getRealScreenSize(getApplicationContext());
    menuV = new MenuView(this);
    menuV.setOnTouchListener(this);
    logoV = new LogoView(this);
    setContentView(logoV);                          Log.d("APP", "SET LOGO VIEW");
//^ This is my splash screen, again irrelevant to the issue, after few seconds of running, this view calls the resume() of my SurfaceView and sets it as the contentView.
}

@Override
protected void onPause() {
    super.onPause();
    Log.d("APP", "ON PAUSE");
    menuV.pause();
}

@Override
protected void onResume() {
    super.onResume();
        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

//^hides the goddamn navigation bar...

    Log.d("APP", "ON RESUME");
    menuV.resume();
}

    @Override
public boolean onTouch(View v, MotionEvent event) {

    if(event.getAction() == MotionEvent.ACTION_DOWN)
    {
        Log.d("APP", "ON TOUCH DOWN");
        for(int i = 0; i < menuV.button.length ; i++)
        {
            if(menuV.button[i].active)
            {
                if(event.getX() > menuV.button[i].pos.left && event.getX() < menuV.button[i].pos.right && event.getY() > menuV.button[i].pos.top && event.getY() < menuV.button[i].pos.bottom)
                {
                    menuV.button[i].pressed = true;
                    return true;
                }
            }
        }
    }
    else if(event.getAction() == MotionEvent.ACTION_UP)
    {
        Log.d("APP", "ON TOUCH UP");
        for(int i = 0; i < menuV.button.length ; i++)
        {
            menuV.button[i].pressed = false;
        }
    }

    return false;
}

所以我的触摸事件由UI线程处理,但它正在访问工作线程一直在使用的信息,同样的事情发生在onPause()和onResume()上,UI线程正在改变“运行” “工作线程总是使用的布尔值,我这样说是因为看起来ANR在触摸屏幕时以及断电和打开电话时都会发生。渲染并没有停止,似乎工作线程很好,但UI线程很糟糕,它停止响应,这条线显示在我的Android监视器上:

线程[2,tid = 18257,WaitingInMainSignalCatcherLoop,Thread * = 0x558cbf1310,peer = 0x12c470a0,“Signal Catcher”]:对信号3作出反应

将堆栈跟踪写入'/data/anr/traces.txt'

如果有任何其他有用的信息,请告诉我 - 我会在此行之后编辑您指出的重要信息,谢谢!

1 个答案:

答案 0 :(得分:0)

尝试将run变量标记为volatile:

volatile boolean run;

也许你有与缓存相关的问题。