TMemoryStream macht Probleme beim wiederholten Aufruf/Zugriff auf den Stream



  • Hallo,

    habe

    TMemoryStream *Stream = new TMemoryStream ;  //Speicher für Screenshot-Stream erzeugen
    

    global deklariert in einer Anwendung mit einem Serversocket, um einen Stream über Socketverbindung zum Client zu übertragen.

    Zunächst sendet der Client ein Zeichen, um den Server zu veranlassen, einen Screenshot vom Bildschirm zu machen. Der Server ruft dazu dann folgende Funktion auf:

    void Screenshot()
    {
      HDC dc = GetDC(NULL);
      TJPEGImage *pJPG_Bild = new TJPEGImage();
      Graphics::TCanvas *ScreenCanvas = new Graphics::TCanvas();
      ScreenCanvas->Handle = dc;
    
      Stream->Clear(); //evtl. alten Inhalt des Streams löschen
    
      Form1->Screenshot->AutoSize = true;
      Form1->Screenshot->Center = true;
      Form1->Screenshot->Top = 0;
      Form1->Screenshot->Left = 0;
      Form1->Screenshot->Picture->Bitmap->Width = Screen->Width;
      Form1->Screenshot->Picture->Bitmap->Height= Screen->Height;
      TRect rect = Rect(0,0,Screen->Width, Screen->Height);
      //Screenshot ist hier ein Bitmap (noch kein jpg!)
      Form1->Screenshot->Picture->Bitmap->Canvas->CopyRect(rect, ScreenCanvas, rect);
      ReleaseDC(NULL,dc);
      delete ScreenCanvas;  //Objekt löschen und Speicher wieder frei geben
    
      //aus Screenshot->Picture ein jpg-Bild erzeugen zum späteren versenden:
      pJPG_Bild->Assign(Form1->Screenshot->Picture->Bitmap);
      pJPG_Bild->CompressionQuality = 50;
      //jpg-Bild in Stream zur Übertragung kopieren:
      Form1->Label1->Caption="Bild vor in Stream schreiben";
      pJPG_Bild->SaveToStream(Stream);
      delete pJPG_Bild;  //Objekt löschen und Speicher wieder frei geben
      Stream->Position=0;  //zum Anfang des Datenstreams gehen
      //Streamgröße (Datenmenge) zuerst übermitteln, damit Empfänger weiß, wann Übertragung zu Ende ist:
    Service1->ServerSocket1->Socket->Connections[0]->SendText(IntToStr(Stream->Size));
       //auf Bestätigung des Client nun warten, damit Stream gesendet werden kann
    }
    

    Daraufhin empfängt der Client die Bildgröße u. quittiert dies mit einem Zeichen an den Server.
    Der Server reagiert wie folgt:

    Stream->Position=0;
               Service1->ServerSocket1->Socket->Connections[0]->SendStream(Stream); //Stream senden
    

    Der Client empfängt den Stream korrekt u. hat so das Bild erhalten, was er wieder mit einem Zeichen an den Server quittiert und die Socketverbindung unterbricht.
    Der Server reagiert so:

    Stream->Clear(); //Stream löschen und damit wieder Speicher freigeben
    

    Dies funktioniert einwandfrei, aber nur einmal!!
    Wiederhole ich die Geschichte, dann bleibt der Server bei der ersten Anweisung, die auf den Stream zugreift (das ist hier "Stream->Clear();" in der obigen Funktion "Screenshot()" hängen.

    Hat jemand eine Idee?
    Liegt dies evtl. an meiner globalen Deklaration von Stream?
    Ich würde ja die Deklaration und die Erstellung des Streams in Screenshot() machen, aber ich brauche ja auch außerhalb dieser Funktion noch einmal den Zugriff auf Stream.

    Danke schon mal!



  • "Bleibt hängen" ist nicht sehr aussagekräftig.

    Ggf. solltest du mal den Code prüfen, mit dem du "außerhalb dieser Funktion noch einmal den Zugriff auf Stream" nimmst.



  • Außerhalb von "Screenshot" ist der Code, den ich unter "Screenshot" gepostet habe. Diese Anweisungen stehen in der ServerSocket1ClientRead-Routine.
    Auch wenn ich nur dort die Anweisung

    Stream->Position=0;
    

    angebe, kommt beim 2. Durchlauf danach keine Reaktion mehr. Habe zum Testen nach "Stream->Position=0;" eine ShowMessage-Anweisung eingefügt. Es kommt keine Message mehr beim 2. Durchlauf.
    Der Memorystream wird doch beim Starten der Anwendung einmal erzeugt. Mit Clear() wird der Stream nach der Übertragung doch wieder rückgesetzt (Inhalt gelöscht), und kann beim 2.mal wieder bearbeitet werden so wie beim 1.mal (nach seiner ursprünglichen Erstellung). Oder habe ich das falsch verstanden? Muss der Stream erst wieder irgendwie initialisiert werden?
    Oder gibt es eine Alternative zum Stream, aber so, dass der Screenshot ohne in einer Datei zwischenzuspeichern, übertragen wird?

    Achso, noch eine Ergänzung:
    Die Anwendung (server) ist übrigens ein Service. Starte ich nach dem 1. erfolgreichen Durchlauf (nach dem 1. übertragenen Screenshot) den Service neu, dann funktioniert das Ganze wieder einmal, aber nicht ein 2.mal hintereinander. Ist definitiv ein Stream-Problem!



  • So, habe jetzt mal folgendes geändert:
    In der Unit des Socketservers:

    public:         // Anwender-Deklarationen
    	__fastcall TService1(TComponent* Owner);
    	TServiceController __fastcall GetServiceController(void);
    	friend void __stdcall ServiceController(unsigned CtrlCode);
            TMemoryStream *Stream;
            void Screenshot(void);
    

    In der ServerSocketClientRead Routine:

    Stream = new TMemoryStream ;    //Speicher für Screenshot-Stream erzeugen
    

    Damit wird ein Stream für die Screenshotübertragung erzeugt, sobald der Client ein bestimmtes Kommandozeichen sendet.
    Screenshot klappt danach prima. Der Screenshot wird einwandfrei übertragen, um am Ende unterbricht der Client die Socketverbindung.
    Beim Server wird daraufhin das Onclientdisconnect-Ereignis ausgelöst, in dessen Routine ich mit

    delete Stream;
    

    den Speicher freigeben möchte. Und genau diese Anweisung funzt nicht!! Ein unmittelbar danach folgendes

    Form1->Label1->Caption=("Stream gelöscht");
    

    wird gar nicht mehr ausgeführt!
    Was soll das? Hilfffe!


Anmelden zum Antworten