2

问题很简单。在 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();
                }
            }
        }
    }
4

1 回答 1

0

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

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

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

于 2013-02-17T15:58:02.687 回答