2013-08-22 3 views
11

Il mio obiettivo è mantenere un oggetto std::thread come membro dati e inizializzarlo quando necessario.
Non riesco a farlo (come nel mio codice di seguito) perché il costruttore di copie della classe std::thread viene cancellato. c'è un altro modo per farlo?È possibile definire uno std :: thread e inizializzarlo in seguito?

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

Passare 'questo' al posto del dereferenziamento' * questo'. –

risposta

3

Il tuo problema è un altro - si sta passando un'istanza MyClass nella filettatura invece che il puntatore MyClass cui il membro le funzioni si aspettano. Semplicemente cambiare DoDiskJobThread() come questo (non dereference 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); 
    } 
} 

si stavano diventando l'errore perché *this portato nel tentativo di copiare MyClass nella funzione filo, e il ctor copia della vostra classe viene cancellato (perché quella di std::thread è cancellato). Tuttavia, le funzioni membro CopyThread e MoveThread richiedono comunque un puntatore come primo argomento (nascosto).

Live demonstration

+0

+1, sì, non ho notato il fatto che sta passando '* this' invece di' this', hai ragione; | –

+1

L'operatore '=' non consente l'assegnazione di un nuovo oggetto thread alla variabile 'DiskJobThread'. Ottengo questo errore: 'errore C2678: binario '=': nessun operatore trovato che prende un operando di sinistra di tipo 'const std :: thread' (o non c'è alcuna conversione accettabile)' – hkBattousai

+0

@hkBattousai Non c'è 'const std :: thread' nel codice che hai postato (e puoi vedere su ideone che il mio cambiamento funziona). Pubblica il tuo codice attuale. – Angew

10

Come avvolgerlo in un puntatore?

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: E sì, gli altri hanno parlato e non ho sentito il bisogno di aggiungere qui, ma al fine di evitare ulteriori downvote palificazione, lo dirò: Si passa *this e non this copiando in tal modo un'istanza della classe. (I problemi sorgono perché è non copiabile domande Pass this e si dovrebbe essere a posto..)

+1

Ora 'thread_ptr' non è più copiabile e non è meno mobile del' DiskJobThread originale ', anche se ... –

+1

@KerrekSB Sì, ma se l'obiettivo è solo inizializzare in un secondo momento, I _think_ non dovrebbe essere un problema; –

+1

-1: Il problema non è con l'inizializzazione di 'std :: thread' (dato che utilizza un op di assegnazione di movimento che va bene), quindi questo non risponde alla domanda. – Angew

4

Non è possibile inizializzare l'oggetto filo dopo che è stato creato; per definizione, l'inizializzazione avviene quando viene creato un oggetto. Ma puoi usare swap per spostare un oggetto filo in un altro:

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

Proprio quello che stavo cercando _std :: swap (thread1, thread2) _ – Charlie

+0

Non funziona. genera questo errore: C: \ Programmi (x86) \ Microsoft Visual Studio 12.0 \ VC \ include \ xmemory0 (611): errore C2280: 'std :: thread :: thread (const std :: thread &)': tentativo di riferimento a una funzione cancellata 1> C: \ Programmi (x86) \ Microsoft Visual Studio 12.0 \ VC \ include \ thread (70): vedere la dichiarazione di 'std :: thread :: thread' 1> Questa diagnostica si è verificata nel compilatore funzione generata 'Abc :: Abc (const Abc &) – codeLover

+0

@codeLover - il problema è nella tua classe 'Abc' che apparentemente ha un' std :: thread' come membro dei dati .. 'std :: thread' non è copiabile, quindi la classe deve disabilitare la costruzione della copia o avere un costruttore di copia che in qualche modo abbia senso per provare a copiare quell'oggetto thread. –