2
votes

I have a function(please see code below) which reads some data from the web. The problem with this function is that sometimes it will return fast but another time it will wait indefinitely. I heard that threads helps me to wait for a definite period of time and return.

Can you please tell me how to make a thread wait for 'x' seconds and return if there is no activity recorded. My function also returns a string as a result, Is it possible to catch that value while using a thread?

 private string ReadMessage(SslStream sslStream)
        {
            // Read the  message sent by the server.
            // The end of the message is signaled using the
            // "<EOF>" marker.
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;

            try
            {
                bytes = sslStream.Read(buffer, 0, buffer.Length);

                // Use Decoder class to convert from bytes to UTF8
                // in case a character spans two buffers.
                Decoder decoder = Encoding.ASCII.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                // Check for EOF.
            }
            catch (Exception ex)
            {

                throw;
            }



            return messageData.ToString();
        }

For Andre Calil's comment:

My need is to read/write some value to a SSL server. For every write operation the server sends some response, The ReadMessage is responsible for reading the incoming message. I've found situations wnen the ReadMessage(sslStream.Read(buffer, 0, buffer.Length);) waits forever. To combat this problem, i considered threads which can wait for 'x' seconds and return after that. Following code demonstrates the working of ReadMEssage

 byte[] messsage = Encoding.UTF8.GetBytes(inputmsg);
            // Send hello message to the server. 
            sslStream.Write(messsage);
            sslStream.Flush();
            // Read message from the server.
            outputmsg = ReadMessage(sslStream);
           // Console.WriteLine("Server says: {0}", serverMessage);
            // Close the client connection.
            client.Close();
4
logeeks, you could call Thread.Sleep(x), where x represents time in milliseconds. However, this would pause the flow of your code. I would like to understand better what you're trying to achieve. Could you please explain better how would you like it to perform? - Andre Calil
Thanks, now I see your point. You could run the Response in a separate thread and, within the main thread, run a stopwatch to now when to abort the other thread. However, this would be overkill. Give a try to @pstrjds suggestion and set the read timeout. - Andre Calil

4 Answers

3
votes

You can't (sanely) make a second thread interrupt the one you're executing this code from. Use a read timeout instead:

private string ReadMessage(SslStream sslStream)
{
    // set a timeout here or when creating the stream
    sslStream.ReadTimeout = 20*1000;
    // …
    try 
    {
        bytes = sslStream.Read(…);
    } 
    catch (IOException) 
    {
        // a timeout occurred, handle it
    }
}

As an aside, the following construct is pointless:

try
{
    // some code
}
catch (Exception ex) {
    throw;
}

If all you're doing is rethrowing, you don't need the try..catch block at all.

2
votes

You can set the ReadTimeout on the SslStream so that the call to Read will timeout after a specified amount of time.

1
votes

If you don't want to block the main thread, use an asynchronous pattern.

Without knowing exactly what you are trying to achieve, it sounds like you want to read data from an SSL stream that may take quite a while to respond, without blocking your UI/main thread.

You can consider doing your read asynchronously instead using BeginRead

Using that approach, you define a callback method that is invoked every time Read has read data and placed it into the specified buffer.

Just sleeping (whether using Thread.Sleep or by setting ReadTimeout on the SslStream) will block the thread this code is running on.

0
votes

Design it to be Asynchronous by putting the ReadMessage in its own thread waiting for the answer. Once the answer is provided create an event back to the main code to handle its output.