Почему код зависает при вызове 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; // до возврата
    }

Другие вопросы по тегам