2017-08-31 3 views
1

Ich schreibe eine Windows 10-Anwendung, die Daten von 4 verschiedenen Sensoren (Encoder und IMUs) über serielle Daten sammelt. Ich schreibe dies in Visual Studio in C++ 11. Ich habe einen Thread pro Sensor, der kontinuierlich Daten von ihm in einer Endlosschleife zieht.C++ - Daten unter Threads teilen

Da ich neu bin, habe ich derzeit Probleme, die Daten in einem einzigen Thread zu sammeln. Ich habe festgestellt, dass ich bedingte Variablen verwenden kann, um einen anderen Thread zu signalisieren (in meinem Fall nehme ich an, dass ich den Haupt-Thread signalisieren würde, wenn jeder Sensor fertig ist). Müsste ich in diesem Szenario die Daten in einer globalen Variablen speichern und mit einem Mutex schützen, während ich in sie schreibe (aus dem Sensor-Thread) und daraus lese (in der Hauptschleife)?

Ich sorge mich jedoch, dass dieser Prozess für meine Anwendung zu langsam sein kann (jeder Sensor erhält neue Daten alle 1-2 ms), und so während des Hauptthreads, würde ich verlieren Daten. Wäre es sinnvoll, innerhalb eines Sensor-Threads die Daten in einer lokalen Variablen zu speichern, diese Variable dann in eine globale Variable zu kopieren und den Haupt-Thread nur aus der 2. Variablen auszulesen?

Ich entschuldige mich, wenn das dumme Fragen sind, aber ich brauche wirklich Hilfe. Jeder Beispielcode würde sehr geschätzt werden.

+0

SO, weniger als 5000 Daten pro Sekunde, Sperre wird kein Problem sein, wenn Daten nicht sehr groß sind. Aber auch Post-Async zu Haupt-Thread kann ein klarer Weg sein. – hiitiger

Antwort

0

Ich würde damit umgehen, indem Sie die Bibliothek boost::asio verwenden, um asynchrone Lesevorgänge für jeden Sensor einzurichten. Wenn ein asynchroner Lesevorgang abgeschlossen ist, ruft er einen Lese-Handler auf, um die Daten zu analysieren, und richtet dann einen weiteren asynchronen Lesevorgang ein. Alle Lese-Handler laufen im selben Thread - was das Leben viel einfacher macht.

1

Das sieht ungefähr so ​​aus, was ich implementieren würde. Ich bezweifle wirklich, dass Sie Schwierigkeiten mit dem Durchsatz haben werden, wenn Sie Millisekunden zwischen der Eingabe haben (das ist eine riesige Menge an Zeit).

Wenn jemand irgendwelche subtilen Bugs in den unten, lass es mich wissen.

#include <thread> 
#include <iostream> 
#include <chrono> 
#include <queue> 
#include <mutex> 
#include <vector> 
#include <condition_variable> 

using namespace std::chrono_literals; 
using std::vector; 
using std::thread; 
using std::unique_lock; 
using std::mutex; 
using std::condition_variable; 
using std::queue; 

class WorkQueue 
{ 
    condition_variable work_available; 
    mutex work_mutex; 
    queue<int> work; 

public: 
    void push_work(int item) 
    { 
    unique_lock<mutex> lock(work_mutex); 

    bool was_empty = work.empty(); 
    work.push(item); 

    lock.unlock(); 

    if (was_empty) 
    { 
     work_available.notify_one(); 
    }  
    } 

    int wait_and_pop() 
    { 
    unique_lock<mutex> lock(work_mutex); 
    while (work.empty()) 
    { 
     work_available.wait(lock); 
    } 

    int tmp = work.front(); 
    work.pop(); 
    return tmp; 
    } 
}; 

int main() { 
    WorkQueue work_queue; 

    auto producer = [&]() { 
    while (true) { 
     work_queue.push_work(10); 
     std::this_thread::sleep_for(2ms); 
    } 
    }; 

    vector<thread> producers; 
    producers.push_back(std::thread(producer)); 
    producers.push_back(std::thread(producer)); 
    producers.push_back(std::thread(producer)); 
    producers.push_back(std::thread(producer)); 

    std::thread consumer([&]() {   
    while (true) 
    { 
     int work_to_do = work_queue.wait_and_pop(); 
     std::cout << "Got some work: " << work_to_do << std::endl; 
    } 
    }); 

    std::for_each(producers.begin(), producers.end(), [](thread &p) { 
    p.join(); 
    });  

    consumer.join(); 
} 
Verwandte Themen