Почему код зависает при вызове cancelInquiry в Java для отмены (запрос Bluetooth) на некоторых телефонах Nokia?
У меня проблема на устройствах Nokia с S40 (но не на S60). проблема заключается в следующем: когда вы вызываете метод cancelInquiry у discoveryAgent из синхронизированного блока, он зависает. на самом деле предполагается перезвонить queryCompleted. код просто зависает - никогда не входит в метод queryCompleted. если то же самое сделано, но не из синхронизированного блока - все работает. Проблема в том, что мне нужно синхронизировать блок, чтобы все в нем выполнялось атомарно в многопоточном приложении.
Вот как выглядит мой DiscoveryListener:
public class DeviceDiscoverer implements DiscoveryListener {
private Object thisCannotBeInterruptedByOtherBlocksLikeIt=new Object();
private boolean stiiInCycle;
private DiscoveryAgent discoveryAgent;
public boolean cancel() { //called from some controller in mid discovery
//synchronized(thisCannotBeInterruptedByOtherBlocksLikeIt) //problem when this is uncommented
{
if (stillInCycle) {
//<some logic>
discoveryAgent.cancelInquiry(this);
//<more logic>
}
}
}
public void inquiryCompleted(int inquiryStatus) { //this is a callback in response to cancel or normal ending
Beeper.beep(); //this makes the phone make a sound
}
// <some irrelevant methods here. some have synchronized blocks like the one above>
}
когда вы запускаете приведенный выше код на s40 и s60 с закомментированным оператором синхронизации и вызываете метод cancel(), немедленно вызывается метод queryCompleted, и вы слышите звуковой сигнал. НО, если вы раскомментируете синхронизированный оператор, вы услышите звуковой сигнал на S60, но на S40 (по крайней мере, на 5-й редакции fp1), queryCompleted никогда не вызывается! (когда я поместил звуковой сигнал непосредственно перед вызовом метода cancelInquiry у discoveryAgent, он подал звуковой сигнал. Когда я разместил его после этого вызова, он не дошел. Это потому, что вызов не возвращается, пока не будет вызван запрос queryCompleted, и этот вызов не произойдет)
в чем проблема? если это ошибка в значении cancelInquiry для S40, как мне обойти это? Я должен синхронизировать, потому что все выполняется параллельно (например, мой код может начать запрос, а затем может отменить его. В то время, когда он отменен, может запускаться startInquiry, может работать deviceDiscovered, может работать queryCompleted и Конечно, параллельно с любым из них, входящий отменить запрос может быть запущен.
я попытался разделить queryCompleted в другой экземпляр прослушивателя, другими словами, вместо вызова discoveryAgent.cancelInquiry(this) я вызвал discoveryAgent.cancelInquiry(anotherInstance), надеясь, что queryCompleted в 'anotherInstance' будет вызван, но нет, он зависает, что так же хорошо.
какие-либо предложения? заранее спасибо
1 ответ
Мне не нравится этот подход, но, поскольку вы не можете использовать синхронизированный... Как насчет занятого цикла ожидания? http://en.wikipedia.org/wiki/Busy_wait
Вы можете попробовать код ниже:
приватная тема cancelThread; public boolean cancel() { синхронизирован (это) { while (cancelThread!= null) { попробуй { Thread.sleep(100); } catch(Exception e) {} } cancelThread = Thread.currentThread(); } // делать свои вещи cancelThread = null; // до возврата }