1

S40を搭載したNokiaデバイスで問題があります(S60では問題ありません)。問題は次のとおりです。同期ブロック内から DiscoveryAgent の cancelInquiry メソッドを呼び出すと、ハングします。実際には、inquiryCompleted をコールバックすることになっています。コードがフリーズするだけで、inquiryCompleted メソッドに入ることはありません。同じことが行われているが、同期されたブロック内からではない場合 - すべてが機能します。問題は、ブロック内のすべてがマルチスレッドアプリでアトミックに実行されるように、ブロックを同期する必要があることです。

これは私の 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() メソッドを呼び出すと、inquiryCompleted メソッドがすぐに呼び出され、ビープ音が聞こえます。ただし、同期ステートメントのコメントを外すと、S60 ではビープ音が聞こえますが、S40 (少なくとも第 5 版 fp1) では、inquiryCompleted は呼び出されません! (discoveryAgentのcancelInquiryを呼び出す直前にビープ音を鳴らしたとき、ビープ音を鳴らしました。その呼び出しの後に配置したとき、そこに到達しませんでした。これは、inquiryCompletedを呼び出すまで呼び出しが返されず、その呼び出しが発生しないためです)

何が問題ですか?S40 の cancelInquiry の impl'n のバグである場合、どうすれば回避できますか? 物事は並行して行われるため、同期する必要があります (たとえば、私のコードは照会を開始し、その後、それをキャンセルする場合があります。キャンセルされた時点で、startInquiry が実行されている可能性があり、deviceDiscovered が実行されている可能性があり、inquiryCompleted が実行されている可能性があります。もちろん、これらのいずれかと並行して、着信 cancelInquiry が実行されている可能性があります。

InquiryCompleted を別のリスナー インスタンスに分離しようとしました。つまり、discoveryAgent.cancelInquiry(this) を呼び出す代わりに、discoveryAgent.cancelInquiry(anotherInstance) を呼び出しました方法も。

助言がありますか?前もって感謝します

4

1 に答える 1

0

私はこのアプローチが好きではありませんが、同期を使用できないため...ビジーな待機ループはどうですか? http://en.wikipedia.org/wiki/Busy_wait

以下のコードを試すことができます。

    プライベート スレッド cancelThread;

    public boolean cancel() {
        同期(これ){
            while (cancelThread != null) {
                { Thread.sleep(100); を試してください。キャッチ(例外e){}
            }
            cancelThread = Thread.currentThread();
        }

        // 自分のことをする

        cancelThread = null; // 戻る前に
    }

于 2012-04-19T11:54:10.173 に答える