SORU
29 Ocak 2011, CUMARTESİ


Nasıl Tetikçi bir iş parçacığı oluşturmak için bir mesajı hemen göndermek?

Arka plan, işlem iletileri oturur bir iş parçacığı var. Şöyle bir şey:

class Worker extends Thread {

    public volatile Handler handler; // actually private, of course

    public void run() {
        Looper.prepare();
        mHandler = new Handler() { // the Handler hooks up to the current Thread
            public boolean handleMessage(Message msg) {
                // ...
            }
        };
        Looper.loop();
    }
}

Ana iş parçacığı (önemli olan UI iş parçacığı değil) böyle bir şey yapmak istiyorum:

Worker worker = new Worker();
worker.start();
worker.handler.sendMessage(...);

Sorun bu ayarlar benim için güzel bir yarış durumu: anda worker.handler okuma imkanı yok emin olmak için bu iş parçacığı zaten atanan bu alan!

Sadece Worker'kurucu ana iş parçacığı üzerinde çalıştığı için s yapıcı Handler yanlış iş parçacığı ile kendisini ilişkilendirmek. dan Handler oluşturun edemem

Bu pek nadir görülen bir senaryo gibi görünüyor. Birkaç geçici çözüm, hepsi çirkin buldum

  1. Şöyle bir şey:

    class Worker extends Thread {
    
        public volatile Handler handler; // actually private, of course
    
        public void run() {
            Looper.prepare();
            mHandler = new Handler() { // the Handler hooks up to the current Thread
                public boolean handleMessage(Message msg) {
                    // ...
                }
            };
            notifyAll(); // <- ADDED
            Looper.loop();
        }
    }
    

    Ve esas konu:

    Worker worker = new Worker();
    worker.start();
    worker.wait(); // <- ADDED
    worker.handler.sendMessage(...);
    

    notifyAll() wait(), o zaman uyanmış olacağız önce olursa! ama bu değildir güvenilir ya da:

  2. Geçen WorkerMessage bir ilk'ler, run() yöntem sonrası sahip kurucu. Geçici bir çözüm, eğer hemen ama kısa bir süre sonra göndermek istemeyiz. eğer birden fazla ileti için çalışmak, ya da olmaz.

  3. handler alana kadar meşgul bekleme artık null. Evet, son çare...

Worker iplik adına Handler MessageQueue bir oluşturmak istiyorum, ama bu mümkün görünmüyor. Bu işten en zarif yolu nedir?

CEVAP
31 Ocak 2011, PAZARTESİ


(Eksi hata denetimi) nihai çözüm, CommonsWare için teşekkürler

class Worker extends HandlerThread {

    // ...

    public synchronized void waitUntilReady() {
        d_handler = new Handler(getLooper(), d_messageHandler);
    }

}

Ve esas konu:

Worker worker = new Worker();
worker.start();
worker.waitUntilReady(); // <- ADDED
worker.handler.sendMessage(...);

Bu tetikçi başlatıldı kadar HandlerThread.getLooper() blok semantiği sayesinde çalışıyor.


Bu arada, bu benim çözüm benzer HandlerThread şöyle kabaca uygulanan açık kaynak aşk lazım () #1 Yukarıda

public void run() {
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Looper.loop();
}

public Looper getLooper() {
    synchronized (this) {
        while (mLooper == null) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
    return mLooper;
}

En önemli fark bu değil olup olmadığını kontrol edin worker çalışıyor, ama aslında oluşturulan bir looper; ve bu yüzden saklamak için looper özel bir alan. Güzel!

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Associated Press

    Associated P

    18 EYLÜL 2006
  • metagamers

    metagamers

    13 Mayıs 2006
  • Rachel Talbott

    Rachel Talbo

    26 Ocak 2011