Pytanie Jak mogę rzetelnie stwierdzić, czy wątek boost zakończył swoją metodę uruchamiania?


Zakładam, że łączenie to wskazywałoby, jednak wydaje się, że tak nie jest.

W klasie robotniczej próbowałem zasygnalizować, że nadal przetwarzał on predykat:

bool isRunning(){return thread_->joinable();}

Czy wątek, który się zakończył, nie byłby dołączalny? Czego mi brakuje ... Jakie jest znaczenie wątku boost :: joinable?


30
2017-11-03 13:45


pochodzenie




Odpowiedzi:


Ponieważ możesz dołączyć do wątku nawet po jego zakończeniu, joinable () będzie nadal zwracać wartość true, dopóki nie wywołasz join () lub detach (). Jeśli chcesz się dowiedzieć, czy wątek nadal działa, powinieneś móc wywołać funkcję timed_join z czasem oczekiwania równym 0. Zauważ, że może to spowodować stan wyścigu, ponieważ wątek może zakończyć się tuż po zakończeniu połączenia.


30
2017-11-03 13:58



To trochę mylące stwierdzenie, że może to doprowadzić do stanu wyścigowego. timed_join sam nie może tego zrobić. jeśli popełnisz błędne założenia na podstawie wyniku połączenia, możesz oczywiście skończyć z wyścigiem, ale to nie ma nic wspólnego z timed_join niż przy założeniu, że wynik tego połączenia jest nadal ważny. W każdym razie +1 - jalf
Myślę, że to jest naprawdę złe. Dlaczego projektanci wspomagania nigdy nie myślą o intuicji ani o początkujących. Wystarczyłaby prosta metoda isRunning (). Zamiast tego zmuszają one do używania funkcji, która nie powinna być intuicyjnie użyta w tym przypadku. Nie chcę próbować dołączać do wątku, chcę tylko szybko sprawdzić, czy nadal coś robi. To jest bzdura. Zmarnowałem dużo czasu, zanim to znalazłem. To nie jest cholerne słowo w "docs". - AndreasT
Wątek może być w 3 stanach: Bieganie, Wolnostojący, Notowanie. - Gaetano Mendola
@AndreasT: Well Boost jest wykonywany przez ludzi jako Ty. Jeśli masz konkretną propozycję, zrób to. Będzie jeszcze lepiej, jeśli dodatkowo dostarczysz łatkę z dokumentacją i testami. - Vicente Botet Escriba
Ta odpowiedź nie jest poprawna, jak w przypadku boostu 1.55 w Windows: timed_joined () jest przestarzałe, a wywołanie try_join_for (0) zwraca wartość false bez sprawdzania, czy wątek się zakończył. Wydano poprawkę dla następujących wersji boost, ale nie jest jasne, jakie zamierzone zachowanie wynika z perspektywy programisty boost: svn.boost.org/trac/boost/ticket/9618 - Ernest_Galbrun


Posługiwać się wątek :: timed_join () z minimalnym limitem czasu. Zwróci wartość false, jeśli wątek nadal działa.


5
2017-11-03 13:58



To nieprawda. Jeśli wątek został odłączony, zwróci false. Rzeczywiście, musisz przeczytać ją w odwrotny sposób: jeśli zwrot jest prawdziwy, wątek był uruchomiony, a następnie zatrzymany w czasie oczekiwania - Gaetano Mendola
@GaetanoMendola: Niezupełnie, wątek można zatrzymać i dołączyć do niego, gdy zadzwonisz timed_join, a wynik będzie prawdziwy. - Vicente Botet Escriba


Zasadniczo nie możesz tego zrobić. Powodem jest to, że dwiema możliwymi odpowiedziami są "Tak" i "Nie, kiedy ostatnio wyglądałem, ale może teraz". Nie ma niezawodnego sposobu na stwierdzenie, że wątek nadal znajduje się w jego metodzie run, nawet jeśli istnieje niezawodny sposób określenia czegoś przeciwnego.


3
2017-11-03 13:57



Zasadniczo mogą Zrób to. Możesz rzetelnie zapytać lub "obserwować" status wątku w danym momencie. Problem polega na tym, że nie możesz wysuwać żadnych założeń dotyczących interakcji w oparciu o otrzymany status, co oznacza, że ​​w momencie, w którym masz informacje "wątek wciąż działa", mógł już zostać zatrzymany w czasie, który potrzebował, aby uzyskać te informacje, ale to rzadko ma znaczenie krytyczne. Przepraszamy, ale ten wpis nie był w żaden sposób pomocny. - AndreasT
@AndreasT: Jeśli nie możesz zrobić żadnych założeń, jak to może być przydatne? - Vicente Botet Escriba


Używam boosta 1.54, dzięki któremu etap timed_join () jest przestarzały. W zależności od użycia możesz użyć joinable (), który działa idealnie do moich celów lub alternatywnie możesz użyć try_join_for () lub try_join_until (), zobacz:

http://www.boost.org/doc/libs/1_54_0/doc/html/thread/thread_management.html


3
2017-10-09 10:34





Trochę to prymitywne, ale jak na razie wciąż działa zgodnie z moimi wymaganiami. :) Używam boost 153 i qt. Stworzyłem wektor int do śledzenia "statusu" moich wątków. Za każdym razem, gdy utworzę nowy wątek, dodaję jeden wpis do wątku thread_ids z wartością 0. Dla każdego utworzonego wątku przekazuję identyfikator, dzięki czemu wiem, jaką część wątków thread_ids mam aktualizować. Ustaw status na 1 dla bieżących i innych wartości w zależności od aktualnie wykonywanej aktywności, więc wiem, jakie czynności zostały wykonane po zakończeniu wątku. 100 to wartość ustawiona dla poprawnie ukończonego wątku. Nie jestem pewien, czy to pomoże, ale jeśli masz inne sugestie, jak to poprawić, daj mi znać. :)

std::vector<int> thread_ids;
const int max_threads = 4;
void Thread01(int n, int n2)
{
    thread_ids.at(n) = 1;
    boost::this_thread::sleep(boost::posix_time::milliseconds(n2 * 1000));
    thread_ids.at(n) = 100;
    qDebug()<<"Done "<<n;

}
void getThreadsStatus()
{
    qDebug()<<"status:";
    for(int i = 0; i < max_threads, i < thread_ids.size(); i++)
    {
        qDebug()<<thread_ids.at(i);
    }
}
int main(int argc, char *argv[])
{
    for(int i = 0; i < max_threads; i++)
    {
        thread_ids.push_back(0);
        threadpool.create_thread(
            boost::bind(&boost::asio::io_service::run, &ioService));
        ioService.post(boost::bind(Thread01, i, i + 2));
        getThreadsStatus();
    }

    ioService.stop();
    threadpool.join_all();
    getThreadsStatus();
}

0
2017-08-12 06:29





Najłatwiejszym sposobem, jeśli funkcja, która uruchamia twój wątek jest dość prosta, jest ustawienie zmiennej na wartość true, gdy funkcja jest zakończona. Oczywiście, potrzebujesz zmiennej na wątek, jeśli masz wiele map z identyfikatorami wątków, a stan może być lepszym rozwiązaniem. Wiem, że jest ręcznie, ale w międzyczasie działa dobrze.

class ThreadCreator
{
private:
    bool            m_threadFinished;
    void launchProducerThread(){
        // do stuff here
        m_threadRunning = true;
    }
public:
    ThreadCreator() : m_threadFinished(false) {
        boost::thread(&Consumer::launchProducerThread, this);
    }
};

0
2017-11-28 01:00





To nie może być bezpośrednia odpowiedź na twoje pytanie, ale widzę koncepcję wątku jako naprawdę lekki mechanizm i celowo pozbawiony niczego poza mechanizmami synchronizacji. Myślę, że właściwym miejscem do umieszczenia "działa" jest klasa, która definiuje funkcję wątku. Zwróć uwagę, że z perspektywy projektowania możesz opuścić wątek przy przerwaniu i nadal nie masz ukończonej pracy. Jeśli chcesz wyczyścić wątek po jego zakończeniu, możesz zawinąć go w bezpieczny wskaźnik i przekazać go klasie robotniczej.


0
2018-02-11 19:06



Uważam, że byłoby lepiej, gdybyś wyjaśnił przykładami kodu i podzielił tekst w paragrafach, aby ułatwić czytelność. - phaberest