2013-08-22 11 views
11

Mein Ziel ist es, ein std::thread Objekt als Datenelement zu behalten und es bei Bedarf zu initialisieren.
Ich kann dies nicht (wie in meinem Code unten), weil der Kopierkonstruktor der Klasse std::thread gelöscht wird. Gibt es einen anderen Weg, es zu tun?Ist es möglich einen std :: thread zu definieren und später zu initialisieren?

class MyClass 
{ 
    public: 
     MyClass():DiskJobThread(){}; 
     ~MyClass(); 

     void DoDiskJobThread(); 

    private: 
     int CopyThread(const std::wstring & Source, const std::wstring & Target); 
     int MoveThread(const std::wstring & Source, const std::wstring & Target); 
     std::thread DiskJobThread; 
}; 

MyClass::~MyClass() 
{ 
    DiskJobThread.join(); 
} 

void MyClass::DoDiskJobThread() 
{ 
    std::wstring Source = GetSource(); 
    std::wstring Target = GetTarget(); 
    int m_OperationType = GetOperationType(); 
    if  (m_OperationType == OPERATION_COPY) 
    { 
     DiskJobThread = std::thread(&MyClass::CopyThread, *this, Source, Target); 
    } 
    else if (m_OperationType == OPERATION_MOVE) 
    { 
     DiskJobThread = std::thread(&MyClass::MoveThread, *this, Source, Target); 
    } 
} 
+2

Führen Sie "this" statt der Dereferenzierung '* this'. –

Antwort

3

Ihr Problem ist etwas anderes - Sie Geben einer Instanz MyClass in das Gewinde anstelle des Zeigers auf MyClass welche das Mitglied Funktionen erwarten. Ändern Sie einfach DoDiskJobThread() wie folgt aus (nicht dereferenzieren this):

void MyClass::DoDiskJobThread() 
{ 
    std::wstring Source = GetSource(); 
    std::wstring Target = GetTarget(); 
    int m_OperationType = GetOperationType(); 
    if  (m_OperationType == OPERATION_COPY) 
    { 
     DiskJobThread = std::thread(&MyClass::CopyThread, this, Source, Target); 
    } 
    else if (m_OperationType == OPERATION_MOVE) 
    { 
     DiskJobThread = std::thread(&MyClass::MoveThread, this, Source, Target); 
    } 
} 

Sie haben den Fehler bekommen, weil *this führte zu versuchen MyClass in die Thread-Funktion zu kopieren und die Kopie Ctor Ihrer Klasse gelöscht wird (denn das ist der std::thread wird gelöscht). Die Elementfunktionen CopyThread und MoveThread erfordern jedoch einen Zeiger als das erste (versteckte) Argument sowieso.

Live demonstration

+0

+1, ja, ich habe nicht bemerkt, dass er '* this' anstelle von' this' geht, du hast recht; | –

+1

Der Operator '=' erlaubt nicht die Zuweisung eines neuen Thread-Objekts zur 'DiskJobThread'-Variable. Ich bekomme diesen Fehler: 'Fehler C2678: binary '=': kein Operator gefunden, der einen linken Operanden vom Typ 'const std :: thread' verwendet (oder es gibt keine akzeptable Konvertierung)' – hkBattousai

+0

@hkBattousai Es gibt keine 'const std :: thread "in den Code, den Sie gepostet haben (und Sie können auf dem Bildschirm sehen, dass meine Änderung funktioniert). Veröffentlichen Sie Ihren tatsächlichen Code. – Angew

10

Wie wäre es mit einem Zeiger?

std::unique_ptr<std::thread> thread_ptr; 

// Look into std::make_unique if possible 
thread_ptr = std::unique_ptr<std::thread>(new std::thread(...)); 

Edit: Und ja, die anderen haben es erwähnt und ich fühle mich nicht die Notwendigkeit, sie hier hinzufügen, aber um mehr downvote Bohlen zu vermeiden, werde ich es sagen: Sie passieren *this und nicht this und kopiert dabei eine Instanz Ihrer Klasse. (Probleme entstehen, weil es nicht kopierbaren Pass this und Sie sollten gut zu gehen..)

+1

Nun ist 'thread_ptr' nicht mehr kopierbar und nicht weniger beweglich als das Original' DiskJobThread', obwohl ... –

+1

@KerrekSB Ja, aber wenn das Ziel nur ist, später zu initialisieren, sollte ich _think_ es sollte kein Problem sein; o –

+1

-1: Das Problem besteht nicht darin, 'std :: thread' zu initialisieren (da es eine Bewegungszuweisungsoperation verwendet, die in Ordnung ist), so beantwortet dies die Frage nicht. – Angew

4

Sie können nicht initialisieren das Thread-Objekt, nachdem es erstellt wird; Per Definition erfolgt die Initialisierung, wenn ein Objekt erstellt wird. Aber Sie können swap verwenden, um ein Thread-Objekt in ein anderes zu verschieben:

std::thread thr1; // no thread of execution 
std::thread thr2(my_function_object); // creates thread of execution 
thr1.swap(thr2); // thr1 is now running the thread created as thr2 
        // and thr2 has no thread of execution 
+0

Genau das, was ich gesucht habe _std :: swap (thread1, thread2) _ – Charlie

+0

Es funktioniert nicht. Dieser Fehler wird ausgegeben: C: \ Programme (x86) \ Microsoft Visual Studio 12.0 \ VC \ include \ xmemory0 (611): Fehler C2280: 'std :: thread :: thread (const std :: thread &)': versucht zu Referenz auf eine gelöschte Funktion 1> C: \ Programme (x86) \ Microsoft Visual Studio 12.0 \ VC \ include \ thread (70): siehe Deklaration von 'std :: thread :: thread' 1> Diese Diagnose ist im Compiler aufgetreten generierte Funktion 'Abc :: Abc (const Abc &) – codeLover

+0

@codeLover - das Problem ist in Ihrer Klasse 'Abc', die anscheinend einen' std :: thread' als Datenmember hat. 'std :: thread' ist nicht kopierbar, also muss Ihre Klasse entweder den Kopieraufbau deaktivieren oder einen Kopierkonstruktor haben, der irgendwie Sinn macht, dieses Thread-Objekt zu kopieren. –

Verwandte Themen