2016-11-23 1 views
1

Ich habe eine Klasse, die die gesamte Geschäftslogik kapselt, die mit der Verwendung von Asio zum Lesen und Schreiben in einen generischen Stream-Socket verbunden ist. Ich möchte eine Markierung hinzufügen, damit meine Benutzer wissen, ob sie Daten von einem Getter abrufen können oder ob wir immer noch auf das Backend warten.Wie kann ich meinem Benutzer mitteilen, dass ein Lesevorgang noch nicht abgeschlossen wurde?

Wie wird das normalerweise gemacht? Setzen Sie nach dem Schreiben ein Flag auf "busy" und führen Sie das Lesen im Hintergrund in einem separaten Thread durch? Das Flag würde etwas ähnlich wie

+0

Definieren Sie ein Ereignis, so dass Sie den Benutzer einen Rückruf geben, wenn die Ressourcen verfügbar sind .... –

+0

Das ist eine Alternative, aber für jetzt muss ich das IsBusy-Flag implementieren. – ruipacheco

+0

IsBusy Flag ist ein Weg, um das Problem zu lösen, müssen Sie Pooling oder lange Pooling tun, die nicht gut ist –

Antwort

2

Ich weiß nicht, ob Sie nach einer asynchronen Lösung suchen, z. B. einen Rückruf oder eine Abrufmethode verwenden. Aus der Frage scheint es, dass Sie nach einer Abfragemethode suchen, da Sie ein Flag möchten, dass Benutzer überprüfen können, ob die Daten vollständig bereit sind. In diesem Fall nur eine Variable und Funktion in Ihrer Klasse, H-Datei definieren:

#include <atomic> 
#include <thread>  

class MySocket 
{ 
public: 
    ~MySocket(); 
    bool IsReady(); 
    void StartDataGather();  
private: 
    void GatherDataThread(); 
    static std::atomic<bool> _isReady; 
    std::thread _thread; 
} 

in Ihrer CPP-Datei:

#include "MySocket.h" 

static std::atomic<bool> MySocket::_isReady(false); // Default flag to false. 

MySocket::~MySocket() 
{ 
    // Make sure to kill the thread if this class is destroyed. 
    if (_thread.joinable()) 
     _thread.join(); 
} 

bool MySocket::IsReady() { return _isReady; } 

void MySocket::StartDataGather() 
{ 
    _isReady = false; // Reset flag. 

    // If your gather thread is running then stop it or wait for it 
    // to finish before starting it again. 
    if(_thread.joinable()) 
     _thread.join(); 

    // Start the background thread to gather data. 
    _thread = std::thread(GatherDataThread()); 
} 

void MySocket::GatherDataThread() 
{ 
    // This is your thread that gathers data. 
    // Once all of the data is gathered, do the following: 
    _isReady = true; 
} 

Um diese Methode von außerhalb Ihrer Client-Klasse verwenden Sie die folgende :

MySocket mySock; 

mySock.StartDataGather(); 

while(!mySock.IsReady()) 
{ 
    // Do some other code here until data is ready. 
    // Once the MySocket::GatherDataThread() finishes it will 
    // set _isReady = true which will cause mySock.IsReady() to 
    // return true. 
} 

Sie haben jetzt eine Flagge, die andere überprüfen und es ist wegen der std::atomic<> Vorlage Thread-sicher. Im Folgenden wird C++ 11 oder neuer -std=c++11 verwendet.

+0

Warum haben Sie _isReady statisch gemacht und keine Instanzvariable? – ruipacheco

+0

Falls mehrere Instanzen der Klasse "MySocket" vorhanden sind. Ich weiß nicht, wie Ihr Code verwendet wird, also musste ich ein paar Dinge erraten. Wenn es in Ordnung ist, mehrere Instanzen der Klasse zu haben, und das 'GatherDataThread' keine gemeinsame Ressource benötigt, dann können Sie das' static' entfernen. Auch hier kommt es darauf an, was Sie in Ihrem Code tun möchten. – user2205930

+0

Danke, das war großartig! – ruipacheco

0

sein, wenn Sie Benutzer Benutzer einer Bibliothek meinen, würde ich empfehlen, das Ergebnis der asynchronen Methode in einem std::future oder ähnlichen Thread-Synchronisationsmechanismus zu umhüllen. Sie können die Methode wait_for verwenden, um fehlzuschlagen und zu melden, dass der Prozess noch läuft, und versuchen Sie es erneut.

+0

Sie meinen, wrap asio :: async_read in einem Std :: Zukunft? – ruipacheco

+1

tbh Ich bin mit Boost asio nicht besonders vertraut, aber ich denke, du denkst zu tief. Das Ergebnis Ihrer Bibliothek ist sicherlich etwas anderes als die direkte Ausgabe des 'async_read'? Nachdem die Callback-Bedingung 'async_read' erfüllt ist, können Sie das' future' mit seinem Ergebnis angeben. – yano

Verwandte Themen