wait()没有在回调中通过notify()发出信号

时间:2013-02-17 15:30:40

标签: java android callback thread-synchronization

问题很简单。在Android上我有一个需要调用库函数的方法。该呼叫将发出我必须处理的回叫信号。在我从我的方法返回之前,我必须等待该回调发出信号。

我认为监视器对象上的wait()和notify()方法可以解决这个问题。它没有。

基本上,监视对象称为Connection,我在调用方法中实例化。然后该方法执行一个循环,它调用Android库方法来“取消注册”一个对象。不幸的是,在一些回调中给出了对这种方法的响应。所以我使用Connection.wait(10000)方法等待回调,在回调中我使用connection.notify()来表示它何时完成(当然所有都是同步的)。但是,connection.notify()不会释放connection.wait(10000)。我可以从Android logcat看到取消注册成功但是我总是需要等待10秒才能尝试下一次取消注册任务。

调用方法和回调的代码如下。我在推理这个失败时做出了什么愚蠢的假设。据我所知,调用方法(线程)肯定拥有监控对象,并将其提供给connection.wait(10000)上的回调!

也许我正在使用一种完全不正确的方法解决这个问题? (我想要的是在完成所有取消注册之前阻止调用者的方法。)

public void clearRegistrations()
{
    connection = new Connection();
    // Tell the callback to notify() when a result is obtained
    connection.setUseNotify(true);
    for(BluetoothHealthAppConfiguration btConfig : btHealthAppConfigs)
    {
        // Initialize Connection object to not connected
        connection.setConnectionState(false);
        if(btHealth.unregisterAppConfiguration(btConfig))
        {
            try
            {
                synchronized (connection) 
                {
                    connection.wait(10000);
                    // See if we were signaled or timed out
                    if(!connection.getConnectionState())
                    {
                        Log.i(TAG, "Unregistration attempt timed out or failed; trying next un-registration");
                    }
                }
            }
            // This should not happen
            catch(InterruptedException ie)
            {
                Log.i(TAG, "The InterrupedException is signaled.");
            }
            // This should not happen.
            catch(IllegalMonitorStateException ime)
            {
                Log.i(TAG, "wait() method threw an IllegalMonitorStateException. Message: " + ime.getMessage());
            }
        }
        else
        {
            Toast.makeText(context, "Un-Registration API returned failure", Toast.LENGTH_SHORT).show();
        }
    }
    btHealthAppConfigs.clear();
    connection.setConnectionState(false);
    connection.setUseNotify(false);
}

回调如下,它与上面的方法在同一个类中,但它是Android中非常流行的'onSomeEvent()'之一:

    public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration btAppConfig, int status)
    {
        if (status == BluetoothHealth.APP_CONFIG_UNREGISTRATION_FAILURE)
        {
            Log.i(TAG, "Un-Registration of the Bluetooth Health Application failed");
            if(connection.useNotify() == true)
            {
                synchronized (connection)
                {
                    Log.i(TAG, "Signal unregistration failure");
                    // just indicate signaled
                    connection.setConnectionState(true);
                    connection.notify();
                }
            }
        }
        else if(status == BluetoothHealth.APP_CONFIG_UNREGISTRATION_SUCCESS)
        {
            Log.i(TAG, "Un-Registration of the Bluetooth Health Application successful");
            if(connection.useNotify() == true)
            {
                synchronized (connection)
                {
                    Log.i(TAG, "Signal unregistration success");
                    connection.setConnectionState(true);
                    connection.notify();
                }
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

这段代码可能有很多问题:assylias得到了大部分内容。显而易见的是,你肯定需要使用notifyAll而不是notify。 notify重启一些等待锁的线程; notifyAll重新启动它们。

useNotify和setConnectionState也需要同步。此外,您还需要保证锁定的连接实例在两个部分中都相同,并且与您调用notify的连接实例相同。最后,您需要保证在等待调用之后实际发生通知调用。

就方法而言,无论何时使用这种低级工具,您都应该想知道是否有更好的方法。有几个更高级别的结构可以更简单地做到这一点。我建议您尝试重新设计代码,以便不等待回调。拨打电话,将状态停放在某处,然后在发生回调时处理回调。