2009-08-24 25 views
15

All'interno della mia app, voglio inviare un messaggio ad una finestra di dialogo da un thread diverso. Voglio passare un riferimento alla classe std :: exception derivato alla finestra di dialogo.Come inviare una stringa tramite PostMessage?

Qualcosa di simile a questo:

try { 
     //do stuff 
} 
catch (MyException& the_exception) { 
    PostMessage(MyhWnd, CWM_SOME_ERROR, 0, 0); //send the_exception or the_exception.error_string() here 
} 

voglio ricevere il messaggio nella mia finestra e mostrare l'errore che è in the_exception.error_string()

LPARAM CMyDlg::SomeError(WPARAM, LPARAM) 
{ 
    show_error(????? 
    return 0; 
} 

passando il std::string the_exception.error_string() utilizzando PostMessage sarebbe anche ok, indovina.

risposta

12

Non è possibile passare l'indirizzo della stringa in PostMessage, poiché la stringa è probabilmente thread-local nello stack. Quando l'altro thread lo preleva, potrebbe essere stato distrutto.

Invece, dovresti creare una nuova stringa o un oggetto eccezione tramite new e passare il suo indirizzo all'altro thread (tramite il parametro WPARAM o LPARAM in PostMessage). L'altro thread quindi possiede l'oggetto ed è responsabile della sua distruzione.

Ecco alcuni esempi di codice che mostra come questo potrebbe essere fatto:

try 
{ 
    //do stuff 
} 
catch (MyException& the_exception) 
{ 
    PostMessage(MyhWnd, CWM_SOME_ERROR, 0, new string(the_exception.error_string)); 
} 


LPARAM CMyDlg::SomeError(WPARAM, LPARAM lParam) 
{ 
    // Put in shared_ptr so it is automatically destroyed. 
    shared_ptr<string> msg = reinterpret_cast<string*>(lParam); 

    // Do stuff with message 

    return 0; 
} 
+1

Ciao, grazie mille per la tua risposta. hai dimenticato il cast per LPARAM PostMessage (MyhWnd, CWM_SOME_ERROR, 0, reinterpret_cast (nuova stringa (the_exception.error_string))); E come usare invece auto_ptr: std :: auto_ptr msg (reinterpret_cast (lParam)); Perché questo mostra il trasferimento di proprietà. – rec

+0

ouch, formattazione errata interruzione linea di test interruzione linea di test – rec

+1

Non si tratta di una perdita di memoria? Dove stai distruggendo mai una nuova stringa()? –

1

Finché ci si trova all'interno di un processo è sufficiente passare un puntatore del vuoto * e un po 'di attenzione sulla durata dell'oggetto sono sufficienti.

Se SendMessage è possibile passarlo in LPARAM come un cast * vuoto, e il client lo ritrasmette al tipo di stringa. Perché SendMessage è synchronous, siete al sicuro:

Se la finestra specificata è stato creato da il thread chiamante, la routine di finestra viene chiamato immediatamente come subroutine. Se la finestra specificata è stata creata da un thread diverso, il sistema passa a quel thread e chiama la procedura appropriata della finestra . I messaggi inviati tra i thread vengono elaborati solo quando il thread di ricezione esegue il codice di recupero del messaggio . Il filo di invio è bloccato fino a quando il filo di ricezione elabora il messaggio

Se si desidera utilizzare PostMessage allora dovrete fare una mano esplicita, perché la chiamata è asincrona: fare una copia della stringa su l'heap e chiamando PostMessage hai passato la responsabilità dell'eliminazione al calee (la finestra di dialogo).

Se si va fuori processo (MyhWnd appartiene a un processo diverso), allora è tutta una storia diversa e dovrete mettere il vostro messaggio in un qualcosa come un atomo globale.

+0

OK, è ora di andare a casa. Ho risposto come se l'OP chiedesse di SendMessage e l'intero punto era PostMessage ... –

+1

Buono a sottolineare che SendMessage è sincrono e non devi preoccuparti di trasferire la proprietà.Tuttavia, SendMessage può essere rientranti, ovvero durante la chiamata a SendMessage il thread potrebbe inviare messaggi, quindi devi stare attento allo stato in cui il tuo passaggio all'altro thread non può essere mutato in nessuno dei tuoi wndprocs. – Michael

+0

IMO questa è la risposta corretta: usa SendMessage e copia il messaggio nel thread ricevente quando lo ricevi. Non c'è bisogno di prepararsi alla bomba con complicati problemi di PostMessage/sincronizzazione per un semplice passaggio di stringa (una stringa che presumo sarà piuttosto breve). – Roel

0

Finché si sa che la finestra (o istanza di CMyDlg) saranno ancora in giro dopo la pubblicazione del messaggio si potrebbe semplicemente negozio la stringa di errore in una variabile membro e leggere da questo nel gestore messaggi.

Problemi correlati