问题很简单。在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();
}
}
}
}
答案 0 :(得分:0)
这段代码可能有很多问题:assylias得到了大部分内容。显而易见的是,你肯定需要使用notifyAll而不是notify。 notify重启一些等待锁的线程; notifyAll重新启动它们。
useNotify和setConnectionState也需要同步。此外,您还需要保证锁定的连接实例在两个部分中都相同,并且与您调用notify的连接实例相同。最后,您需要保证在等待调用之后实际发生通知调用。
就方法而言,无论何时使用这种低级工具,您都应该想知道是否有更好的方法。有几个更高级别的结构可以更简单地做到这一点。我建议您尝试重新设计代码,以便不等待回调。拨打电话,将状态停放在某处,然后在发生回调时处理回调。