[C++] Wątki modyfikujące konkretną linię w konsoli.
Ostatnio zmodyfikowano 2017-11-29 23:23
kmlkamilek Temat założony przez niniejszego użytkownika |
[C++] Wątki modyfikujące konkretną linię w konsoli. » 2017-11-28 20:24:43 Nie mam pojęcia jaki dać tytuł, więc wymyśliłem coś takiego na poczekaniu. Gryzie mnie pewna rzecz. Na potrzeby pytania z góry załóżmy, że chcę napisać pewien menedżer pobierania, który będzie wykorzystywał API współbieżności. Pobieram 4 pliki. Chcę w konsoli wyświetlać aktualny postęp, który dla każdego pliku, byłby aktualizowany przez przeznaczony do tego wątek. Chcę mieć coś takiego: 1. Downloaded 3 of 400 KB 2. Downloaded 5 of 250 KB 3. Downloaded 4 of 100 KB 4. Downloaded 8 of 120 KB
By na końcu otrzymać coś takiego: 1. Downloaded 400 of 400 KB 2. Downloaded 250 of 250 KB 3. Downloaded 100 of 100 KB 4. Downloaded 120 of 120 KB
#include <iostream> #include <string> #include <thread> #include <vector> #include <atomic> #include <mutex> #include <chrono> #include <random>
std::atomic < unsigned > counter; std::mutex print_lock;
void print( unsigned index, unsigned bytes_to_download ) { using namespace std::chrono_literals; int i = 0; while( i < bytes_to_download ) { if( print_lock.try_lock() ) { std::cout << "\r" << index << ". Downloaded " << i + 1 << " of " << bytes_to_download << "KB" << std::flush; print_lock.unlock(); i++; counter++; std::this_thread::sleep_for( 20ms ); } } }
int main() { std::mt19937_64 rnd { std::random_device { }() }; std::uniform_int_distribution < unsigned > dist( 100u, 500u ); std::vector < std::thread > threads; for( unsigned i = 0; i < 8; i++ ) threads.emplace_back( & print, i + 1, dist( rnd ) ); for( auto && thread: threads ) thread.join(); std::cout << "\nDownloaded " << counter << " bytes\n"; return 0; }
Próbowałem zrobić coś sam, ale ten program wyświetla wynik w jednej linii z wątku, ktory akurat w danym momencie zablokuje sobie cout'a. Z góry dziękuję. PS: Jeśli ktoś ma zamiar pisać, bym zrobił to w jednym wątku, w pętli i po prostu czyścić konsole, to niech nie pisze. |
|
Kinexity |
» 2017-11-28 20:41:16 Jeżeli piszesz pod Win, to w WinAPI są funkcje służące do modyfikacji zawartości konsoli. |
|
kmlkamilek Temat założony przez niniejszego użytkownika |
» 2017-11-28 20:44:44 Wiem o tym, ale zależy mi by było to zaimplementowane, przy użyciu standardowego API c++. |
|
jankowalski25 |
» 2017-11-28 21:08:56 Standardowa biblioteka C++ sama z siebie nie zapewnia możliwości cofnięcia się o jeden wiersz do góry, jeśli o to pytasz (bo nie ma takiego znaku specjalnego). |
|
Kinexity |
» 2017-11-28 21:16:24 C++ nie ma "standardowego API", a standardową bibliotekę. Konsola zawsze podlega pod system, więc nawet jeżeli nie chcesz używać systemowego API, to musisz skorzystać z np. Qt lub czegoś podobnego.
EDIT: Nie wspominając o tym, że w konsoli można pisać tylko w jednym punkcie jednocześnie. |
|
kmlkamilek Temat założony przez niniejszego użytkownika |
» 2017-11-29 23:23:15 @Kinexity Miałeś rację. Na windowsie bez winapi nie jest to do ugryzienia, bo jednak trzeba manipulować pozycją kursora. Na uniksowych, sekwencje ucieczki ansi. Na siłę w windzie też można użyć ansi, ale na systemach starszych od Win 10, wsparcie dla ansi w konsoli jest domyślnie wyłączone. |
|
« 1 » |