Android线程/处理程序错误IllegalStateException:尚未发布指定的消息队列同步障碍标记 [英] Android Thread/Handler Error IllegalStateException: The specified message queue synchronization barrier token has not been posted

查看:1993
本文介绍了Android线程/处理程序错误IllegalStateException:尚未发布指定的消息队列同步障碍标记的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做什么

使用处理程序和后台线程每3秒更新一次UI线程上的TextView x 10次。 UI上的输出应该是重复:1开始,每3秒开始,它应该是++的数字。例如,重复:1在3秒后更新为重复:2,然后在3秒后更新为重复:3。

Update TextView on the UI Thread every 3 seconds x 10 times using a Handler and a background thread. The output on the UI should be "Repeat: 1" to begin with and after every 3 seconds, it should ++ the number. Eg "Repeat: 1" updates to "Repeat: 2" after 3 seconds and then to "Repeat: 3" after further 3 seconds.

我是怎样的尝试这样做

我测试的第一个方法是使用带有Thread.sleep()的for循环来为每个导致第二次延迟环。在每个循环中,我调用sendMessage(message)方法,我的理论是每次都会调用UI Thread上的handleMessage()方法。以下是代码:

The first method that I am testing is to use a for loop with a Thread.sleep() to cause a n second delay for each loop. In each loop, I call the sendMessage(message) method and my theory is that the handleMessage() method on the UI Thread will be called every time. Here is the code:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private TextView repeat;
    private Handler mHandler;
    private Thread backgroundThread;
    private String uiString;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate(Bundle) called by Gil ");

        repeat = (TextView)findViewById(R.id.view_repeat);
        runInBackground();
        backgroundThread.start();
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message message) {
                Bundle bundle = message.getData();
                uiString = bundle.getString("count");
                repeat.setText("Repeat: " + uiString);
            }
        };
    }


    public void runInBackground() {
        Log.d(TAG, "runInBackGround() called by Gil");

        backgroundThread = new Thread(new Runnable() {
            @Override
            public void run() {

                Log.d(TAG, "Background Thread started by Gil");
                Bundle bundle = new Bundle();
                Message message = new Message();

                for (int i = 1; i < 11; i++) {

                    bundle.putString("count", ""+i);
                    message.setData(bundle);
                    mHandler.sendMessage(message);

                    try {
                        // delay for 3 seconds
                        Thread.sleep(3000);
                    } catch (Throwable t) {
                        Log.d(TAG, "Throwable Error caused by Thread.Sleep() & Gil");
                    }

                }

            }
        });

    }

}

我运行时的结果

它更新一次:重复:1 - >重复:2然后应用程序自行停止/退出。错误堆栈跟踪如下:

It updates once: "Repeat: 1" --> "Repeat: 2" and then the application stops/quits by itself. The error stack trace is as follows:

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: personal.development.gilho.timerstuff, PID: 29226
                  java.lang.IllegalStateException: The specified message queue synchronization  barrier token has not been posted or has already been removed.
                      at android.os.MessageQueue.removeSyncBarrier(MessageQueue.java:289)
                      at android.os.Looper.removeSyncBarrier(Looper.java:316)
                      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1251)
                      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6521)
                      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:813)
                      at android.view.Choreographer.doCallbacks(Choreographer.java:613)
                      at android.view.Choreographer.doFrame(Choreographer.java:583)
                      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:799)
                      at android.os.Handler.handleCallback(Handler.java:733)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:146)
                      at android.app.ActivityThread.main(ActivityThread.java:5679)
                      at java.lang.reflect.Method.invokeNative(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:515)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
                      at dalvik.system.NativeStart.main(Native Method)
Application terminated.

到目前为止我做了什么


  1. SO问题:建议使用 dispatchMessage()而不是 sendMessage()。试了一下,发生了同样的错误。

  2. 这个问题:与我的问题非常相似,但没有答案,建议试用一本关于游戏开发的书。

  3. 这个SO问题:似乎是一个不同的问题,因为这里的问题与回收消息,而这里没有回收。

  4. SO问题:结果类似,但没有重复尝试不断更新处理程序。答案也不适用于我的场景。

  1. This SO Question: recommends using dispatchMessage() instead of sendMessage(). Tried it and the same error happens.
  2. This SO Question: very similar problem as mine but there was no answer and the comments recommended to try a book on game development.
  3. This SO Question: appears to be a different problem as the problem here related to recycling the message whereas there is no recycling happening here.
  4. This SO Question: the outcome is similar but not there is no repeated attempt to continuously update the handler. The answer also not applicable to my scenario.

我怀疑带有 Thread.sleep的for循环( )每个循环中的方法是我想要做的愚蠢的实现。我的下一个选择是尝试使用CountDownTimer,Handler的现有延迟函数,如 sendMessageDelayed() postDelayed()。最后,我将尝试使用计时器

I suspect that a for loop with a Thread.sleep() method in each loop is a stupid implementation of what I am trying to do. My next choices are to try to use a CountDownTimer, Handler's existing delay functions like sendMessageDelayed() or postDelayed(). Finally, I will try to use a Timer.

但是现在,我想帮助理解为什么这样做我在尝试其他解决方案之前没有学习。我无法使用stacktrace中提供的信息来成功识别出错的地方,也没有在调试模式中查看每一行帮助我。

But for now, I would like help to understand why this isn't working to learn before I try other solutions. I havent been able to use the information provided in the stacktrace to successfully identify what is going wrong nor has looking at each line in debug mode helped me.

推荐答案

问题是使用消息对象。它是一个瞬态对象,所以一旦它被发送到 Handler ,后台线程就不再使用它了。接收线程在那时拥有它。改变你的后台线程做这样的事情:

The problem is the use of Message object. It is a transient object, so once it has been sent to the Handler, the background thread should no longer use it. The receiving thread "owns" it at that point. Change you background thread to do something like this:

for (int i = 0; i < 11; i++) {
    Message msg = mHandler.obtainMessage(MY_MESSAGE_ID, i, 0);
    msg.sendToTarget();

    //  Delay or otherwise wait
}

在你的UI线程的处理程序,然后您可以获取消息并处理它:

On your UI thread's handler, you can then get the message and process it:

@Override
public void handleMessage(Message message) {
    switch (message.what) {
        case MY_MESSAGE_ID:
            repeat.setText("Repeat: " + message.arg1);
            break;

        default:
            Log.w(TAG, "Invalid message received: " + message.what);
            break;
    }
}

这篇关于Android线程/处理程序错误IllegalStateException:尚未发布指定的消息队列同步障碍标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆