Problem mit RichEdit StreamCallback
-
Hallo,
erst mal danke für deine Antwort. Ich versteh was du meinst, mit deiner Hilfestellung, aber es ist definitiv nicht so, dass der Schreibvorgang den Lesevorgang behindert oder diese sich irgendwo kreuzen.
der Fehler passiert in folgender Funktion. Wie du dort siehst, wird GetStreamCallback (Zeile 12) vor der Funktion SetStreamCallback (Zeile 21) angesprochen. Also der Lesevorgang, kann nicht durch den Schreibvorgang beeinflusst werden. Es gibt auch keine andere Funktion in der Klasse, die auf das RichEdit Steuerelement zugreift.void CEMailSendStatusDlg::SetStatusText () { /************************************************************************************************************************************** SET STATUS TEXT übergibt den Text aus der m_sStatus Variable an das RichEdit Steuerelement **************************************************************************************************************************************/ //-------------------------------------------------------------------------------------------------------------- // Bisherigen Text aus dem Steuerelement auslesen // Merke: // - GetTextStream gibt hier keine Werte zurück, weil in der Funktion CRichEdit::_GetStreamCallback // die übergebenen werte nicht in die Temporäre Datei geschrieben werden. LPSTR lpszBuffer = NULL; m_CR_Status.GetTextStream(lpszBuffer); //-------------------------------------------------------------------------------------------------------------- // Bisherigen und neuen Text zusammenführen string sBuffer = lpszBuffer; sBuffer += (::lstrlen(lpszBuffer) > 0) ? CRLF : _T(""); sBuffer += m_sStatus; _DELETE(lpszBuffer); //-------------------------------------------------------------------------------------------------------------- // Text in das Steuerelement setzen m_CR_Status.SetTextStream((LPSTR)sBuffer.c_str()); m_CR_Status.LineScroll(m_CR_Status.GetLineCount()); m_sStatus.clear(); }
Ich Beschreibe mal das ganze Scenario...
CEMailSendStatusDlg Ist ein kleiner Dialog mit zwei Steuerelementen. Einem Progressbar- und einem RichEdit Steuerelement. Der Dialog dient dazu, mir den Versendestatus von E-Mails anzuzeigen. Das RichEdit empfängt dabei solche Nachrichten wie "Start SSL" "Login Ok" usw. Die Progressbar zeigt an wie viele Bytes bisher gesendet wurde.In der Klasse CEMailSendStatusDlg starten 2 Threads die via CreateThread erstellt werden und die in einer while Schleife mit WaitOnAddress Angehalten werden.
In dem EMailDialog in dem ich die E-Mail erstelle, anzeige und versende, wird der EMailStatus Dialog, vor dem versenden der E-Mail und dem Thread der die E-Mail versendet, gestartet.
Aus einer Klasse die in der Hierarchie etwas unterhalb der EMailDialog Klasse liegt, werden dann die Wert für den EMailStatus Dialog gesetzt und die beiden WaitOnAddress Funktionen aufgeweckt, woraufhin die Progressbar und das RichEdit Steuerelement aktualisiert wird.
Das Ganze funktioniert soweit ganz gut, ich komme auch über WM_GETTEXT Nachricht an die bisherigen Werte des RichEdit Steuerelementes. Generell würde ich aber dennoch gerne verstehen, warum ausgerechnet in dem Moment GetStreamCallback versagt.
-
Mir ist Dein Code zu kompliziert. Für was benötigst Du die Datei, wenn Du nur die Daten kopieren willst?
Wir kommst Du darauf, dass Du den Puffer, den Die die Callback Funktion gibt, löschen zu dürfen?
-
Die Datei hFile benötige ich um mit dieser Funktion werte in Dateien (C:\test.txt) zu schreiben oder aus ihr zu lesen.
das gegenstück zu Get- & SetTextStream ist Get- &SetFileStreamWir kommst Du darauf, dass Du den Puffer, den Die die Callback Funktion gibt, löschen zu dürfen
welchen puffer meinst du?
-
Zeile 117
memset(lpBuff,0,cb);
-
weil in dem puffer, alte werte stehen bleiben, wenn die vorhergehende Zeichenfolge länge war, als die aktuelle. deshalb kam ich auf die Idee den zu löschen. ansonsten gibt es keinen Grund dafür.
steht ja auch im Kommentar darüber.
-
Und was interessiert dich das bitte?
Der Callback sagt Dir genau wie weit Du den Speicher zu benutzen hast. Du hast da gar nichts selbst zu ermitteln.
-
LowFly so wie du dir vorgestellst hast, der Code aus deinem ersten Post einfach in Thread packen und ausfuhren, so wird nicht funz.
Du versuchst aus dem Thread auf RichEdit Steuerelement mit Funktion "StreamOut" zugreifen(Threadübergreifend), dein richtige Lösung ist "Threadübergreifende programmierung",schau im netz ob wad findest, ansonsten kann ich dir paar links zu Dokus & Beispiele posten. Kannst dir sicher sein, dass du in deinem Projekt/Code wirst einiges ändern müssen.
-
@MR C
Ah ok,
ja dann poste doch mal die links bitte
-
Mal Grundsätzlich: Du hast also einen anderen Thread der auf das RTF Control zugreift?
Wenn dem so ist, kannst Du den gleich wieder vergessen, weil jede Interaktion letzten Endes durch die Messagequeue synchronisiert wird.Zudem besteht ja sogar die Möglichkeit, dass sich das Control in der Größe bereits verändert hat und entsprechend der Buffer gar nicht passt.
Weiterhin ist nach wie vor, Dein Code ein Witz.
Wir kommst Darauf über strlen auf die Größe eines allokierten Buffers zu schließen? Wenn also im letzten Zyklus nur noch ein Byte übertragen wurde wir dim nächsten Durchgang alles byteweise durchlaufen obwohl der Buffer ursprünglich mal größer war.Dein ganzer Konstrukt mit dem Buffer der irgendwie erhalten bleibt und wieder verwendet wird hat viel zu viele Seiteneffekte.
Ich sehe auch keinen Schutz, dass dieser Buffer nicht aus zwei Threads verwendet werden könnte.Ich habe das mal durchgespielt und bekomme Deine Probleme nicht.
Allerdings kollekiert mein Program einfach alle Daten in einem Puffer.Ich würde davon ausgehen, dass Du einfach einen Fehler in Deinem Code hast.
-
LowFly schau hier rein...
Einführung in Threads:
https://msdn.microsoft.com/de-de/library/ms171728(v=vs.110).aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-1
https://www.labri.fr/perso/betrema/winnt/frogfly1.html
(+SourceCode):
http://www.ucancode.net/Visual_C_MFC_Samples/WaitForSingleObject-_beginthreadex-SetEvent-Start-Stop-Thread-VC-MFC-Example.htm
http://flylib.com/books/en/4.348.1.78/1/
http://www.tenouk.com/visualcplusmfc/visualcplusmfc22.html
https://www.tutorialcup.com/cplusplus/multithreading.htmBeispiele:
http://www.codeproject.com/Articles/14746/Multithreading-Tutorial
http://www.codeproject.com/Articles/43994/The-Practical-Guide-to-Multithreading-Part
http://www.cppfun.com/win32-multi-threads-programming.htm
-
Martin er kann fehler suchen solange es geht. Er hat doch geschrieben, dass der Code ohne Thread funz tadenlos. Ohne "Threadübergreifende programmierung" kommt er kein Schritt weiter. Er greift nicht mit Thread auf RichEdit, sondern aus dem Thread auf RichEdit und so einfach geht das nicht, in NET mus er mit Ivnoke arbeiten.
-
Mit einem Thread ist das doch sowieso quatsch. Er verwendet SendMessage. Also gibt es eine Threadsynchronisation. Da muss man in der Windows API gar nichts machen. Aber ein Thread bringt hier auch keinerlei Vorteile.
-
...fur die hintergrund events ohne die GUI Threads oder andere events zu blockieren wie z.b Emails in Dateien archivieren oder Email versenden und empafngen,usw.... bringen Threads seine voteile.
-
Klar bringen Threads was, aber nur dann wenn sie hinreichend von der UI entkoppelt werden.
Und hier nicht, wenn er SendMessage verwendet und ausgerechnet, dass für eine Operation die länger dauern kann.
-
Martin des habe ich schon erwähnt...wiederhole nicht, dass was ich schon geschrieben habe.