gpt4 book ai didi

android - 同线程情况下如何避免GLSurfaceView出现queueEvent

转载 作者:行者123 更新时间:2023-11-30 03:52:16 25 4
gpt4 key购买 nike

我正在编写在其他线程处理 Android OpenGL 的程序。但是在这段代码的情况下它会卡住。例如,如果是同一个线程,它直接处理方法而不调用 task.get()。有这种方式吗?

public void onSurfaceCreated(GL10 arg0, EGLConfig arg1)
{
Thread t = new Thread(new Runnable(){
@Override
public void run()
{
FutureTask<Object> task = new FutureTask<Object>(new Callable<Object>() {
@Override
public Object call() {
return null;
}
});
gv.queueEvent(task);
try{
task.get();
}catch(Exception e){

}
Log.i("MainActivity", "Done"); // <- Work
}
});
t.start();

FutureTask<Object> task = new FutureTask<Object>(new Callable<Object>() {
@Override
public Object call() {
return null;
}
});
gv.queueEvent(task);
try{ task.get(); }catch(Exception e){} // <- Freeze
Log.i("MainActivity", "Done");

最佳答案

如果我正确解释了您的问题,则您希望在 OpenGL 线程中运行一些代码而不使用FutureTaskRunnable或其他异步解决方案。

首先,这段代码(及其任何数据)是否依赖于其他线程?是否需要与其他代码/数据同步?如果是,那么您应该从不同的线程使用 queueEvent()。由于您想完全留在 OpenGL 线程中,因此我假设您要执行的代码与其他(非 GL)线程没有任何关系。

此外,永远不要从与应该执行 FutureTask 代码的线程相同的线程调用 FutureTask.get() - 如果您的线程正在等待自己?如果你想从另一个线程发送代码到 GL 线程,不要使用 FutureTask;只需为它使用简单的 Runnable(作为 queueEvent() 的参数)。

回到主要问题:要在没有 queueEvent() 的情况下从 GL 线程运行某些东西,您应该决定您想要执行该工作的具体方式,即应该在何时(何地)调用它.你想在每次调用 onDrawFrame() 时调用它吗?或者每次调用 onSurfaceChanged()onSurfaceCreated() 时?

由于您使用了 queueEvent(),我假设您希望您的代码在下一次即将到来的 onDrawFrame() 调用之前运行。在Android GL线程中,在内部,调用顺序如下:

  1. Android 处理所有排队的事件(我对此进行了一些简化,但要点没问题)
  2. 如果需要,Android 会调用 onSurfaceCreated()
  3. 如果需要,Android 会调用 onSurfaceChanged()
  4. Android 调用 onDrawFrame()

因此,简单来说,您使用 queueEvent() 添加的代码将在下一个渲染周期 (onDrawFrame()) 之前执行。如果要在onDrawFrame()中的GL线程上运行这段代码,可以将其添加到onDrawFrame()的开头,例如:

@Override
public void onDrawFrame(GL10 gl) {
if (mDoJob) {
mDoJob = false;

// perform code
}

...
}

这里,mDoJob 是一个volatile 变量。您可以从另一个线程将其设置为 true但是,请注意,这假定您不需要与使用 mDoJob 信号的其他线程进行任何额外的同步,即所有将在 mDoJob 条件 block 无需与其他任何进一步同步就可以了。

基本上,我上面介绍的只是一个简化的(非同步的)解决方案来替换 queueEvent(),它假定您不需要同步(也包括最新的变量) ) 与其他线程。

如果你不需要任何信号(与其他线程的任何依赖),mDoJob 的值可以在 OpenGL 线程内部决定(在 onDrawFrame() 内部) , onSurfaceCreated()onSurfaceChanged()), 那么 mDoJob 不需要是可变的。在这种情况下,您将停留在 OpenGL 线程内,因此不需要异步(因此是同步)解决方案。

总结一下,具体来说,如果你想在onSurfaceCreated()中决定一个代码是否应该在onDrawFrame()中运行,就用一个(non-volatile) bool 变量,您在 onSurfaceCreated() 中设置,然后在 onDrawFrame() 中检查它(如我上面的代码示例中所示)。

关于android - 同线程情况下如何避免GLSurfaceView出现queueEvent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13946992/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com