Multitasking in C++ ??!!
-
Hallo Leute ich güße euch
hab eine kleines aber bedeutendes Problem und bräuchte kompetene Hilfe ...
Möchte in C++ Daten über serielle Port schicken - das Funktioniert auch. Ich klicke auf einen Button "Port öffnen" und er öffnet sich. Dann klicke ich auf Senden und in der Funktion "OnBTNSenden" rufe ich die Funktion "SendData" auf. Diese sendet dann einen String an einen COM-Port, solange bis ...
Und hier setzt mein Problem an: Ich kann das Senden nicht abbrechen. Ich will es nicht, dass der String 10 mal gesendet wird und dann von alleine aufhört. Ich möchte, dass er solange sendet, bis ich auf den Button Abbrechen klicke!!
Das geht aber nicht, da ich ja noch in der Funktion "SendData" fest sitzte, die in der Prozedur "OnBTNSenden" aufgerufen wurde --> d.h. dass die Prozedur "OnBTNSenden" ja auch noch nicht beendet ist und somit kann ich nichts mehr machen - und das Programm stürtzt später ab.
Geht denn kein Multitasking in C++ sodass das Senden im Hintergtrund agieren kann, bis ich "Abbrechen" drücke ?!
Bitte helft mir
Danke
-
Jason20 schrieb:
Hallo Leute ich güße euch
hab eine kleines aber bedeutendes Problem und bräuchte kompetene Hilfe ...
Möchte in C++ Daten über serielle Port schicken - das Funktioniert auch. Ich klicke auf einen Button "Port öffnen" und er öffnet sich. Dann klicke ich auf Senden und in der Funktion "OnBTNSenden" rufe ich die Funktion "SendData" auf. Diese sendet dann einen String an einen COM-Port, solange bis ...
Und hier setzt mein Problem an: Ich kann das Senden nicht abbrechen. Ich will es nicht, dass der String 10 mal gesendet wird und dann von alleine aufhört. Ich möchte, dass er solange sendet, bis ich auf den Button Abbrechen klicke!!
Das geht aber nicht, da ich ja noch in der Funktion "SendData" fest sitzte, die in der Prozedur "OnBTNSenden" aufgerufen wurde --> d.h. dass die Prozedur "OnBTNSenden" ja auch noch nicht beendet ist und somit kann ich nichts mehr machen - und das Programm stürtzt später ab.
Geht denn kein Multitasking in C++ sodass das Senden im Hintergtrund agieren kann, bis ich "Abbrechen" drücke ?!
Bitte helft mir
Danke
Natürlich geht das. Du kannst ja in deinem GUI(DLG) Code einen Senden-Thread starten, der das Senden der Daten übernimmt. In diesem Threadcode überpüfst du dann das Abbruchkriterium (z.B. ob die Abbruchtaste betätigt wurde). Wenn ja, beendest du das Senden und brichst ab.
// thread code UINT DownloadThreadFunc(LPVOID data){ // daten senden etc. while(!bAbort){ // send a byte or something } return 0; } //dialog code: aufruf des threads. z.B. so: AfxBeginThread(DownloadThreadFunc, data, THREAD_PRIORITY_ABOVE_NORMAL); //1.Arg: Threadname //2.Arg: LPVOID data //3.Arg: Priorität // Mehr dazu in der MSDN, hier in der FAQ oder via Suchfunktion
-
Danke für den Vorschlag,aber er ist mir doch ein wenig zu hoch.
UINT DownloadThreadFunc(LPVOID data)
Was soll da für data eingesetzt werden. den String den ich senden will ist vom Typ CString
und das alles zusammen kapier ich auch irgendwie nich
AfxBeginThread(DownloadThreadFunc, data, THREAD_PRIORITY_ABOVE_NORMAL);
mir fehlt dazu ein simles Beispiel-has du da zufällig was parat. oder könntestdu es näher erklären, was ich alles noch brauche
thanks
-
Jason20 schrieb:
Danke für den Vorschlag,aber er ist mir doch ein wenig zu hoch.
UINT DownloadThreadFunc(LPVOID data)
Was soll da für data eingesetzt werden. den String den ich senden will ist vom Typ CString
Du brauchts ja nicht nur den String zum Senden sondern auch den Port und deine Abbruchsvariable.Ich würde da einen Zeiger auf meinen Dialog rein packen.
Jason20 schrieb:
und das alles zusammen kapier ich auch irgendwie nich
AfxBeginThread(DownloadThreadFunc, data, THREAD_PRIORITY_ABOVE_NORMAL);
mir fehlt dazu ein simles Beispiel-has du da zufällig was parat. oder könntestdu es näher erklären, was ich alles noch brauche
thanksAfxBeginThread = Starte die Funktion in einen eigenen Thread
DownloadThreadFunc = Die Funktion die du starten willst
data = Die Parameter der Funktion
THREAD_PRIORITY_ABOVE_NORMAL = Gib den Thread mehr Rechenzeit als dem Dialog
-
hab das jetzt folgendermaßen umgesetzt
UINT CBspDlg::DownloadThreadFunc(LPVOID data) { while(!bSenden) { SendData(); } return 0; }
bool CBspDlg::SendData() { CString csString; m_ctrlLIST_String.GetText(0,csString); csSerial.SendData(csString); return true; }
void CBspDlg::OnBTNSenden() { UpdateData(TRUE); CBspDlg test; bSenden = true; AfxBeginThread( DownloadThreadFunc , NULL , THREAD_PRIORITY_ABOVE_NORMAL ); UpdateData(FALSE); }
"error C2665: 'AfxBeginThread' : Durch keine der 2 Ueberladungen kann Parameter 1 vom Typ 'unsigned int (void *)' konvertiert werden"
versteh ich nicht
-
Die Threadfunktion muss global sein ausserdem muss du noch etwas an deinen Funktionen ändern:
void CBspDlg::OnBTNSenden() { UpdateData(TRUE); CBspDlg test; bSenden = true; AfxBeginThread( DownloadThreadFunc , this , THREAD_PRIORITY_ABOVE_NORMAL ); UpdateData(FALSE); } UINT DownloadThreadFunc(LPVOID data) { CBspDlg * dia = (CBspDlg *) data; while(!dia->bSenden) { dia->SendData(); } return 0; }
-
Andorxor schrieb:
UINT DownloadThreadFunc(LPVOID data) { CBspDlg * dia = (CBspDlg *) data; while(!dia->bSenden) { dia->SendData(); } return 0; }
bSenden darf nicht als 'private' deklariert sein. (so hab ich es zumindest noch in erinnerung
while(!dia->bSenden) { dia->SendData(); }
Wenn sendData z.B. ca. 30 sek. dauert, dann kann der Benutzer zwar die 'bSenden' Variable auf false setzen, doch die Methode 'sendData' wird trotzdem bis zum Schluss abgearbeitet.
man müsste also irgendwie ne 'sendByte(BYTE by)' Methode haben, die jeweils nur 1 Byte sendet. So hat man eine bessere Möglichkeit, den transfer zu beenden.//z.B. // baData: CByteArray mit n Bytes for(int i=0; i<baData.GetSize(); i++){ if(dlg->bSenden){ sendByte(baData.getAt(i)); } else return 0; }
aus meiner Sicht, ist dies allerdings wieder eine "Entkapselung". D.h. schlau wäre es, wenn eine sendMethode bestehen würde, die die kompleten Daten sendet (wie oben bereits von <Andorxor> geschrieben).. Aber wie kommuniziert dann die Methode mit dem Thread, falls die Methode vorher verlassen werden muss? Eine 'bSend' Variable auch noch in der SendData-Methode? Ist doch hässlich oder? Wie könnte man es daher besser machen?
-
ich hätte es über nachrichten gelöst
-
Horst2 schrieb:
ich hätte es über nachrichten gelöst
Könntest du das noch einwenig besser erläutern?
-
ich würde die abfrage auf das senden nicht in der Schleife, sondern in der Senddata() funktion machen.
zum abbrechen schickt man eine Nachricht, wodurch das senden abgebrochen wird (die abbruchvariable wird also gesetzt).
eine andere möglichkeit ist es sich eine eigene Threadklasse zu schreiben. Unter anderem könnte es dort eine Methode OnThreadRun() geben, die immer wieder ausgeführt wird solange sie true zurück liefert. dann ist es auch ein leichtes sich methoden zu schreiben, die den Thread unterbrechen oder beenden.
-
JASON20 schreibt:
hab es jetzt mit einen Timer umgesetzt
unter: http://download.pearsoned.de/leseecke/VCPLUS6_21Tg/data/start.htm
Das hat mir alles unkompliziert gebracht, was ich wollte.
Danke jedochauch für die guten und schnellen Beiträge von euch