0

ユーザーが [開始と中止] を押すボタンに応じて、スレッドを開始、一時停止、再起動する必要があるアプリケーションをプログラミングしています。スレッドを制御するために、次のように、アクティビティと連携するサービスを作成します。

活動のコード

public class SoundLocalizer extends Activity {

 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(D) Log.e(TAG, " ON CREATE ");

        // Set up the window layout
        setContentView(R.layout.main);

    }

     public void onStart() {
        super.onStart();
        if(D) Log.e(TAG, "++ ON START ++");

        mHelloService = new HelloMessage(ThisContext, mHandler, LocalIP);
        mHelloService.start();

        setup();
    }


    public void onReStart(){

        mHelloService.restart();
    }

    public void onWait(){

        mHelloService.stop();

        if(D) Log.e(TAG, "-- ON WAIT --");
    }

    private void setupChat() {
        Log.d(TAG, "setupChat()");


        mStartButton = (Button) findViewById(R.id.btnStart);
        mStartButton.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {

                //The aplicacion have already been lauched
                if(Begin){

                    onReStart();
                }
                isRecording = true;
                enableButtons(false);



            }
        });

        mAbortButton = (Button) findViewById(R.id.btnAbort);
        mAbortButton.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {

                enableButtons(true);

                Loop=false;
                isRecording=false;
                WaitForMaster=false;
                onWait();   
                Begin=true;


            }
        });

}



}

サービスコード

public class HelloMessage {

    Context mContext ;
    private final Handler mHandler;     
    private boolean Working=true;


    public HelloMessage(Context context, Handler handler, String IP){

        mContext=context;
        mHandler = handler;
        Local_IP_String=IP;
        String[] IP_Parts = IP.split("\\.");
        LocalIP=Integer.parseInt(IP_Parts[3]);

     }

     public void restart() {        

     Working=true;               

    /*
    mHelloThread.notify();
    */

 }


 public synchronized void start() {

    Working=true;                
    mHelloThread = new HelloThread();
     mHelloThread.start();

     }


public void stop() {

    Working=false;

            /*
    try {
        mHelloThread.wait();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

     */

    }

public class HelloThread extends Thread {

     DatagramSocket mSocket ;
     InetAddress myBcastIP;  

        public HelloThread() {

            try { 

                       //Here I initialize some variables

             } catch (IOException e) { 

                 ...
             }

        }

        public void run(){

            //Listen on socket to receive messages 
            try{                

                        while(Working){                 

                                  //Do things

                            }

                        }


             } catch (IOException e) { 

                      ...

             }


}

問題: Abort を押すと、アクティビティで mHelloService.stop() が正しく呼び出され、フラグWorkingfalseになり、サービスのスレッドの「While ループ」が機能しなくなります。

この時点まで、すべてが完璧です。しかし、その後、 WorkingをtrueにするメソッドmHelloService.restart()を呼び出してループを再開したいのですが、スレッドは再び開始されません。私は何を間違っていますか?

------------ 他のバージョンも試してみましたが、さらに悪い結果になりました ---------------

mHelloService.stop() でmHelloThread.wait( ) を使用し、mHelloService.restart()でmHelloThread.notify () を使用する

LogCatでこれを取得しました:

09-02 02:08:54.640: D/AndroidRuntime(17463): VM をシャットダウンしています 09-02 02:08:54.640: W/dalvikvm(17463): threadid=1: キャッチされない例外で終了するスレッド (group=0x413eb300) 09 -02 02:08:54.648: E/AndroidRuntime(17463): 致命的な例外: メイン 09-02 02:08:54.648: E/AndroidRuntime(17463): java.lang.IllegalMonitorStateException: オブジェクトが wait() の前にスレッドによってロックされていません09-02 02:08:54.648: E/AndroidRuntime(17463): java.lang.Object.wait(ネイティブ メソッド) で 09-02 02:08:54.648: E/AndroidRuntime(17463): java.lang.Object で.wait(Object.java:364) 09-02 02:08:54.648: E/AndroidRuntime(17463): android.nacho.SoundLocalizer.HelloMessage.stop(HelloMessage.java:88) 09-02 02:08:54.648 : E/AndroidRuntime(17463): android.nacho.SoundLocalizer.SoundLocalizer.onWait(SoundLocalizer.java:367) 09-02 02:08:54.648: E/AndroidRuntime(17463):android.nacho.SoundLocalizer.SoundLocalizer$3.onClick(SoundLocalizer.java:441) 09-02 02:08:54.648: E/AndroidRuntime(17463): android.view.View.performClick(View.java:4084) 09 -02 02:08:54.648: E/AndroidRuntime(17463): android.view.View$PerformClick.run(View.java:16966) 09-02 02:08:54.648: E/AndroidRuntime(17463): Android で.os.Handler.handleCallback(Handler.java:615) 09-02 02:08:54.648: E/AndroidRuntime(17463): android.os.Handler.dispatchMessage(Handler.java:92) 09-02 02:08 :54.648: E/AndroidRuntime(17463): android.os.Looper.loop(Looper.java:137) 09-02 02:08:54.648: E/AndroidRuntime(17463): android.app.ActivityThread.main( ActivityThread.java:4745) 09-02 02:08:54.648: E/AndroidRuntime(17463): java.lang.reflect.Method.invokeNative(ネイティブ メソッド) 09-02 02:08:54.648:E/AndroidRuntime(17463): java.lang.reflect.Method.invoke(Method.java:511) 09-02 02:08:54.648: E/AndroidRuntime(17463): com.android.internal.os.ZygoteInit で$MethodAndArgsCaller.run(ZygoteInit.java:786) 09-02 02:08:54.648: E/AndroidRuntime(17463): com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 09-02 02 :08:54.648: E/AndroidRuntime(17463): dalvik.system.NativeStart.main(ネイティブメソッド)

お時間をいただきありがとうございました


注 1:

mHelloThread.start() を restart() に追加すると、LogCat で次のようになります。

09-02 03:05:07.664: D/AndroidRuntime(17657): VM をシャットダウンしています 09-02 03:05:07.664: W/dalvikvm(17657): threadid=1: キャッチされない例外で終了するスレッド (group=0x413eb300) 09 -02 03:05:07.672: E/AndroidRuntime(17657): 致命的な例外: メイン 09-02 03:05:07.672: E/AndroidRuntime(17657): java.lang.IllegalThreadStateException: スレッドは既に開始されています。09-02 03:05:07.672: E/AndroidRuntime(17657): java.lang.Thread.start(Thread.java:1045) 09-02 03:05:07.672: E/AndroidRuntime(17657): Android で。 nacho.SoundLocalizer.HelloMessage.restart(HelloMessage.java:67) 09-02 03:05:07.672: E/AndroidRuntime(17657): android.nacho.SoundLocalizer.SoundLocalizer.onReStart(SoundLocalizer.java:353) 09-02 03:05:07.672: E/AndroidRuntime(17657): android.nacho.SoundLocalizer.SoundLocalizer$2.onClick(SoundLocalizer.java:421) 09-02 03:05:07 で。

4

1 に答える 1

1

少し的外れ: なぜすべてを手作業で行いたいのですか? あなたの「サービス」クラスの意味は何ですか? Android を実装する場合は、それをService拡張Serviceしてマニフェストに追加する必要があります。


特定の質問に対して:restartメソッドはスレッドを再起動せず、変数のみを変更します。start完全に停止したため、再度呼び出す必要があります(runメソッドは完全に実行され、変数はチェックされなくなります)。実行中のインスタンスが 1 つだけであることを確認する必要がある場合は、他の同期方法を使用できます。

シングルThreadは 1 回しか実行できないため、新しいスレッド オブジェクトを作成するか、独自の開始動作を実装する必要があります (スレッドが中断されるまで待機させるなど)。

ところで、変数Workingはスレッドセーフではありません。volatile可能性のある同期の問題を回避するようにマークしてください。

于 2013-09-02T00:24:18.837 に答える