none
StreamReader

    Frage

  • Hi,
    ich lese über einen StreamReader Daten ein.
    Das Endekriterium ist mit dem Zeichen (char)10 definiert worden.
    Jetzt habe ich teils den Fall, dass das Zeichen nicht gesendet wird und ich in einer Endlosschleife
    hänge. Welche Lösungsmöglichkeiten gibt es zu diesem Problem?
    Wie kann es zu diesem Problem, der Endloschleife kommen?
    Selbst wenn kein char(10) ausgelesen werden kann, müsste ich doch eine Exception erhalten
    oder sehe ich das falsch?
    Ich könnte evtl. noch ReadLine nehmen, sollte sich das Endezeichen ändern, wäre das ein Problem.
    Oder müsste ich einen eigenständigen Timeout implementieren
    Bis zu Zeit n sollte das Zeichen char(10) vorhanden sein.
    Wenn ja, wie macht man das dann?
    Danke für Tipps.
    myStreamReader.BaseStream.ReadTimeout = 10000;
    try
    {
     int oLoop = 0;
     int i = 0;
     bool whole = false;
     while (true)
     {
      int length = myStreamReader.Read(buffer, 0, buffer.Length);
      for (i = 0; i < length; i++)
      {
       receive[oLoop + i] = buffer[i];
       if (buffer[i] == (char)10 ) 
       {
        whole = true;
        break;
       }
      }
      oLoop += i;
      if (whole)
       break;
     }
    /////
    var watch = System.Diagnostics.Stopwatch.StartNew();
    //  length = myStreamReader.Read(buffer, 0, buffer.Length);
    var elapsedMs = watch.ElapsedMilliseconds;
    if ( elapsedMs > 1000 )
      break;
    Gruß, Markus

    Montag, 4. Dezember 2017 17:24

Antworten

  • Hallo Markus,

    ich hoffe, dass ich die Frage richtig verstehe, in diesem Sinne also die folgende Antwort:

    Stell dir mal vor, du öffnest einen FileStream und willst dann Daten lesen. Das machst du mit der Read-Methode. Du liest immer eine bestimmte Portion, bis du ans Ende des Streams angekommen bist.

    Du legst jetzt zum Beispiel für den Reader (für einen Aufruf der Read-Methode) einen TimeOut-Wert von 1000ms fest.

    Das Lesen einer "Portion" dauert normal nur z.B. 0.01ms. Am Ende des Streams dauert die Read-Methode praktisch 0ms, da nichts mehr zu lesen da ist. Eine Zeitüberschreitung kann also normal nicht passieren.

    Nun geht dir während eines Read-Vorgangs die Festplatte kaputt und die Methode stockt, die Read-Methode hängt, jetzt wird die im TimeOut definierte Zeit überschritten und die Ausnahme generiert. Dein TimeOut bezieht sich nur auf den aktuellen Lesevorgang, nicht darauf, ob Daten vorhanden sind oder nicht.

    Also, wenn dein Stream keine Daten (mehr) hat, hat das nichts mit dem TimeOut des Readers (...der Read-Methode...) zu tun. Die Read-Methode ist sofort zurück und liefert dir: 0 (Byte gelesen). Diese 0 kommt nicht "vom Stream".

    "...Ich dachte, wenn ich nichts lese, erfolgt Timeout nach n Zeit. ..."

    Wenn du nichts liest, wirst du auch nie einen TimeOut erhalten ;-)

    Zitat, TimeOut: Gets or sets a value, in miliseconds, that determines how long the stream will attempt to read before timing out.

    Vermutliche wolltest deiner eigenen Methode einen TimeOut-Mechanismus verpassen. Das scheint mir allerdings keine gute Idee zu sein, zumal du das Problem ja mittlerweile identifizieren konntest und es eine angemessenere Lösung gibt.

    Nun noch zum "TCP-Kram". Wenn du da noch nie etwas mit zu tun hattest, würde ich zunächst eine ausgiebige Einarbeitung in die Thematik vorschlagen.  

    Dasselbe zur Frage "...async - Task wait...", aber hier ein Beispiel: Async Programming : Asynchronous TCP Sockets as an Alternative to WCF

    Gruß

    • Als Antwort markiert Markus Freitag Donnerstag, 7. Dezember 2017 17:35
    Mittwoch, 6. Dezember 2017 20:49

Alle Antworten

  • Hallo Markus,

    deine Variable "length" nimmt irgendwann, falls das Stopp-Zeichen nicht gefunden wird, den Wert 0 an (= keine weiteren Zeichen, bis Ende gelesen). Für diesen Fall: "Nicht gefunden" ist kein Ausstieg aus der Schleife vorgesehen.

    Daneben würde ich noch, falls nicht anders geregelt, das "using (...) {...}"-Konstrukt empfehlen, z.B. so:

    static void Main(string[] args) {
      string testDatei = @"\test.txt";
      int fundstelle = 0;
      using ( var myStreamReader = new StreamReader(testDatei) ) {
        char[] buffer = new char[1024];
        int pos = 0;
        while ( fundstelle == 0 ) {
          int gelesen = myStreamReader.Read(buffer, 0, buffer.Length);
          if ( gelesen == 0 ) { break; }
          for ( int i = 0 ; i < gelesen ; i++ ) {
            if ( buffer[i].Equals((char)10) ) {
              fundstelle = pos + i;
              break;
            }
          }
          pos += gelesen;
        }
      }
      Console.WriteLine($"Gefunden bei Position: {fundstelle}");
      Console.ReadKey();
    }
    Gruß


    • Bearbeitet K. Pater Montag, 4. Dezember 2017 23:51
    Montag, 4. Dezember 2017 23:47
  • Hi K. Pater,
    ja funktioniert bei einer Datei.
    Aber wie sieht das bei einem Socket, Client aus.
    Dachte dann wäre das Timeout.
    Weißt Du das noch, ob ich das so auch erschlagen kann.
    Kann das auch nicht richtig testen.
    Falls Du da noch einen Tipp hättest wäre es toll.
    Gruß, Markus
    TClient = new TcpClient();
    TClient.Connect(ip, port);
    NWStream = TClient.GetStream();
    NWStream.ReadTimeout = 1000; 
    NWStream.WriteTimeout = 1000;
    myStreamReader = new StreamReader(NWStream, new UTF8Encoding(false));
    myStreamWriter = new StreamWriter(NWStream, new UTF8Encoding(false)) { AutoFlush = true };
    //..
    // myStreamReader.BaseStream.ReadTimeout = 1000;
    //..
    string testDatei = @"..\..\test.txt";
    int fundstelle = 0;
    using (var myStreamReader = new StreamReader(testDatei))
    {
     //myStreamReader.BaseStream.ReadTimeout = 1000;
     char[] buffer = new char[1024];
     int pos = 0;
     while (fundstelle == 0)
     {
      int gelesen = myStreamReader.Read(buffer, 0, buffer.Length);
      if (gelesen == 0)
      {
       break;
      }
    Dienstag, 5. Dezember 2017 17:22
  • Hallo Markus,

    ob du einen Timeout festlegen willst, ist eine Frage der Strategie bzw. was bewirkt werden soll. Nach Ablauf des Timeouts wird eine spezielle Exception generiert, die du behandeln könntest. Nach meinem Verständnis sollte ein Timeout aber nur erreicht werden, wenn etwas zu lange dauert, also nicht der Erwartung entspricht.

    Das Problem in deinem ursprünglichen Code war ja unter bestimmten Bedingungen eine Endlosschleife.

    Mit der Festlegung eines Timeouts "erschlägst" du aber höchstens ein anderes Problem, nämlich dass zum Beispiel deine Netzwerk-Verbindung zu langsam ist oder hängt. Das hat nichts mit dem ursprünglichen Problem zu tun und führt dich in diesem Kontext nur auf einen Holzweg.

    Wenn du das "testen" möchtest, würde ich erst einmal eine einfache Client/Server Anwendung erstellen. Vielleicht auch dies. Und damit dann nach und nach die gewünschten Aufgaben implementieren.

    Allgemeine und spezielle Infos zu "Streams" etc. findest du auch noch hier, dort einfach das Ziel-Framework auswählen und z.B. "Stream" in das Suchfeld eintragen.

    Gruß, K. 

    Dienstag, 5. Dezember 2017 18:55
  • Hi K. Pater,
    ja passt mal.
    Was mir unklar ist.
    Unterschied Timeout und 0
    In dem Server Beispiel wird auch auf 0 abgeprüft.
    Ich dachte, wenn ich nichts lese, erfolgt Timeout nach n Zeit.
    Kann ich dennoch eine 0 lesen, warum auch immer.
    // Perform a blocking call to accept requests.
    // You could also user server.AcceptSocket() here.
    TcpClient client = server.AcceptTcpClient();            
    Console.WriteLine("Connected!");
    data = null;
    // Get a stream object for reading and writing
    NetworkStream stream = client.GetStream();
    int i;
    // Loop to receive all the data sent by the client.
    while((i = stream.Read(bytes, 0, bytes.Length))!=0) 
    {   
      // Translate data bytes to a ASCII string.
      data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
      Console.WriteLine("Received: {0}", data);

    Hab mir die Beispiele noch angeschaut.

    if (bytesRead > 0) {  
    	// There might be more data, so store the data received so far.  
    state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));  
    
    	// Get the rest of the data.  
    	client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,  
    		new AsyncCallback(ReceiveCallback), state);  
    } else {  
    	// All the data has arrived; put it in response.  
    	if (state.sb.Length > 1) {  
    		response = state.sb.ToString();  
    	}  
    	// Signal that all bytes have been received.  
    	receiveDone.Set();  
    }
    Ganz einfach nicht zu verstehen, kennst Du evtl. noch Beispiele mit den
    neuen Schlüsselwörter async - task  wait.
    Soll dann etwas lesbarer werden bzw. auch sein. Vielleicht hast ja einen Link, ein Beispiel parat.
       
    Gruß, Markus

    Mittwoch, 6. Dezember 2017 17:24
  • Hallo Markus,

    ich hoffe, dass ich die Frage richtig verstehe, in diesem Sinne also die folgende Antwort:

    Stell dir mal vor, du öffnest einen FileStream und willst dann Daten lesen. Das machst du mit der Read-Methode. Du liest immer eine bestimmte Portion, bis du ans Ende des Streams angekommen bist.

    Du legst jetzt zum Beispiel für den Reader (für einen Aufruf der Read-Methode) einen TimeOut-Wert von 1000ms fest.

    Das Lesen einer "Portion" dauert normal nur z.B. 0.01ms. Am Ende des Streams dauert die Read-Methode praktisch 0ms, da nichts mehr zu lesen da ist. Eine Zeitüberschreitung kann also normal nicht passieren.

    Nun geht dir während eines Read-Vorgangs die Festplatte kaputt und die Methode stockt, die Read-Methode hängt, jetzt wird die im TimeOut definierte Zeit überschritten und die Ausnahme generiert. Dein TimeOut bezieht sich nur auf den aktuellen Lesevorgang, nicht darauf, ob Daten vorhanden sind oder nicht.

    Also, wenn dein Stream keine Daten (mehr) hat, hat das nichts mit dem TimeOut des Readers (...der Read-Methode...) zu tun. Die Read-Methode ist sofort zurück und liefert dir: 0 (Byte gelesen). Diese 0 kommt nicht "vom Stream".

    "...Ich dachte, wenn ich nichts lese, erfolgt Timeout nach n Zeit. ..."

    Wenn du nichts liest, wirst du auch nie einen TimeOut erhalten ;-)

    Zitat, TimeOut: Gets or sets a value, in miliseconds, that determines how long the stream will attempt to read before timing out.

    Vermutliche wolltest deiner eigenen Methode einen TimeOut-Mechanismus verpassen. Das scheint mir allerdings keine gute Idee zu sein, zumal du das Problem ja mittlerweile identifizieren konntest und es eine angemessenere Lösung gibt.

    Nun noch zum "TCP-Kram". Wenn du da noch nie etwas mit zu tun hattest, würde ich zunächst eine ausgiebige Einarbeitung in die Thematik vorschlagen.  

    Dasselbe zur Frage "...async - Task wait...", aber hier ein Beispiel: Async Programming : Asynchronous TCP Sockets as an Alternative to WCF

    Gruß

    • Als Antwort markiert Markus Freitag Donnerstag, 7. Dezember 2017 17:35
    Mittwoch, 6. Dezember 2017 20:49
  • ich hoffe, dass ich die Frage richtig verstehe, in diesem Sinne also die folgende Antwort:

    Hallo K. Pater,

    ja richtig erkannt und DANKE. Ich schau mir das TCP an, ggf. muss ich nochmals nachfragen. Ich suche einfach eine WPF Applikation, Server, Client, evtl. auch mal wo beide kommunizieren, sprich Vollduplex.

    Gruß, Markus


    Donnerstag, 7. Dezember 2017 17:37