von Thread auf Variablen zugreifen?!?
-
hi skyp21b,
ich bekomme leider eine access violation wenn ich deinen code versucheUINT CDlgBeepThreadDlg::thrFunc_3(LPVOID pParam) { int zahl; zahl = 1; int times; HWND hWnd = (HWND)pParam; CDlgBeepThreadDlg* pDlg = (CDlgBeepThreadDlg*) pParam; times = pDlg->timesleep; while(g_bCont) { zahl = zahl +1; ::SendMessage(hWnd, U_WM_BEEP, zahl, 0); Sleep(times); } return 0; }
wenn ich diese zeile rausnehm, und den code entsprechen ändere bekomme ich keinen fehler
times = pDlg->timesleep;
ne idee?!?
danke
-
youCanCallMeAl schrieb:
ich bekomme leider eine access violation
Hast du denn bei AfxBeginThread einen CDlgBeepThreadDlg* übergeben?
-
so hab ich gemacht
m_pThread = AfxBeginThread(thrFunc_3, m_hWnd);
bin mir nicht sicher ob ich versteh was du meinst....
-
Du kannst von allen Sachen die du aus deiner Applikation (App-Klasse) gestartet hast auf diese zugreifen.
mit der Funktion AfxGetApp()
Vielleicht nützt die das was
-
youCanCallMeAl schrieb:
so hab ich gemacht
m_pThread = AfxBeginThread(thrFunc_3, m_hWnd);
bin mir nicht sicher ob ich versteh was du meinst....
Das, was du bei AfxBeginThread als zweiten Parameter angibst, landet als pParam in deiner Threadfunktion. Wenn du ein HWND reingibst, und hinterher so tust, als ob es ein CDlgBeepThreadDlg* wäre, darfst du dich nicht wundern, wenn's knallt.
-
wenn ich dich richtig verstanden hab (entschuldige vorher die blöde frage :-))
ich sollte als 2 parameter einen zeiger nicht ein handle übergeben?
wie macht man das, bzw. ich habe irgendwo gelesen das zeiger nicht "threadsafe" wären?und bekomme ich durch die zeile
CDlgBeepThreadDlg* pDlg = (CDlgBeepThreadDlg*) pParam;
nicht einen zeiger auf den dialog.
mein c++ zeigt mir bei pDlg->"alle variablen und funktionen" des dialogs an.
greif ich drauf zu knallts....
-
youCanCallMeAl schrieb:
ich sollte als 2 parameter einen zeiger nicht ein handle übergeben?
Was du übergeben "sollst", hängt davon ab, was du in dem Thread brauchst.
wie macht man das, bzw. ich habe irgendwo gelesen das zeiger nicht "threadsafe" wären?
Ein Zeiger an sich ist erst mal gar nichts. Was du mit dem Zeiger machst, ist u.U. nicht threadsafe. Z.B. darfst du aus dem Workerthread nicht mit dem UI interagieren, aber das hast du ja offenbar nicht vor. Du holst ja nur den Member timesleep aus der Instanz.
und bekomme ich durch die zeile
CDlgBeepThreadDlg* pDlg = (CDlgBeepThreadDlg*) pParam;
nicht einen zeiger auf den dialog.
Du interpretierst das, was in pParam steckt, als Zeiger auf deinen Dialog. Dadurch ist es aber noch lange keiner. Dein Auto wird auch nicht zum Hubschrauber, nur weil du es sagst, es sei einer.
Ist der Aufruf von AfxBeginThread in einer Memberfunktion von CDlgBeepThreadDlg? Dann kannst du als zweiten Parameter this übergeben, wie in sky21bs Beispiel.
-
youCanCallMeAl schrieb:
mein c++ zeigt mir bei pDlg->"alle variablen und funktionen" des dialogs an.
greif ich drauf zu knallts....ist auch völlig logisch, da deine Variable pDlg vom Typ CDlgBeepThreadDlg* ist und somit auch alle Variablen und Methoden hat. Das Problem ist der Zeiger den du castest.
Theorethisch kannst du auch ein char* nach CDlgBeepThreadDlg* casten.
übergebe als zweiten parameter (Beim Threadaufruf) mal den this-Zeiger
[edit] zu langsam
[/edit]
-
ok, übergebe ich den this zeiger, funktioniert der zugriff auf die dialog variablen,
wie schaff ichs jetzt noch dass ::SendMessage(hWnd, U_WM_BEEP,0,0) funktionier?
brauch ich den handle für sendmessage?
-
du kannst ja nun auch direkt auf die vars zu greifen.
als parameter nutzt du pDlg->m_hWnd, wobei pDlg der gecastete this-zeiger ist
-
Doppelpost
Nachfolgeversion ist besser..
-
Das Beispiel ist auf das Wichtigste beschränkt.
Keine MessageMap und Co.
Ich greife vom Thread nur indirekt auf Methoden zu.
Der Thread dient eigentlich nur dazu eine andere Methode meiner Klasse aufzurufen!//NThreadDlg.h class CNThreadDlg : public CDialog { protected: // unser Datenlieferant für den Thread struct tdata { CNThreadDlg * pDlg; size_t Range; tdata(CNThreadDlg * dlg, size_t range = 100) : pDlg(dlg) , Range(range) {} }; bool m_bRun; CWinThread* m_pThread; void run(size_t range); void start(); void stop(); static UINT RUNNER(LPVOID); };
//NThreadDlg.cpp CNThreadDlg::CNThreadDlg(CWnd* pParent /*=NULL*/) : CDialog(CNThreadDlg::IDD, pParent) , m_bRun(false) , m_pThread(0) {} UINT CNThreadDlg::run(size_t range) { m_ctrlProgressBar.SetRange32(0, range); while(m_bRun ) { m_ctrlProgressBar.StepIt(); _sleep(500); // sonst sieht man nur Geflacker! } } void CNThreadDlg::start() { m_bRun = true; m_pThread = AfxBeginThread(RUNNER, new tdata(this, 230)); } void CNThreadDlg::stop() { m_bRun = false; } UINT CNThreadDlg::RUNNER(LPVOID param) { tdata data = *(static_cast<tdata*>(param)); return data.pDlg->run(data.Range); }
Das ganze hat meiner Meinung nach den Vorteil, dass die Datenkapselung erhalten bleibt.
Nur meine Klasse und Kinder kennen die Threadmethode.
Durch mein Übergabestruct kennt der Thread (ist ja klassenübergreifend) seine Klasse.