How to avoid Stream.Read() block when internet connection is suddenly down?
-
I send web requests and read data web response:
using (Stream stream = response.GetResponseStream())
{
Data = new byte[response.ContentLength];
int offset = 0;
int count = (int)response.ContentLength;
int nBytes = 0;
int nTotalBytes = 0;
while ((nBytes = stream.Read(Data, offset, count)) > 0)
{
offset += nBytes;
count -= nBytes;
nTotalBytes += nBytes;
}
}If internet connection is suddenyl down Read() function blocks forever. Is there a way to avoid it using the same Read() method?
Чесноков
-
I send web requests and read data web response:
using (Stream stream = response.GetResponseStream())
{
Data = new byte[response.ContentLength];
int offset = 0;
int count = (int)response.ContentLength;
int nBytes = 0;
int nTotalBytes = 0;
while ((nBytes = stream.Read(Data, offset, count)) > 0)
{
offset += nBytes;
count -= nBytes;
nTotalBytes += nBytes;
}
}If internet connection is suddenyl down Read() function blocks forever. Is there a way to avoid it using the same Read() method?
Чесноков
It won't block forever, only until your network stack notices that the stream is no longer valid. But that can be quite a long time :laugh: . The short answer is no, Read is a blocking call. If you want to protect yourself from this possibility, you should do I/O in a background thread, or use asynchronous socket calls (Begin/EndRead etc).
-
I send web requests and read data web response:
using (Stream stream = response.GetResponseStream())
{
Data = new byte[response.ContentLength];
int offset = 0;
int count = (int)response.ContentLength;
int nBytes = 0;
int nTotalBytes = 0;
while ((nBytes = stream.Read(Data, offset, count)) > 0)
{
offset += nBytes;
count -= nBytes;
nTotalBytes += nBytes;
}
}If internet connection is suddenyl down Read() function blocks forever. Is there a way to avoid it using the same Read() method?
Чесноков
As Bob already said, Read() is blocking. As the operation can be long-winding due to the amount of data, the lack of speed of the connection, or the potential failure of the transmission, you should be doing this on a background thread, allowing your app to continue its normal operation (at the bare minimum take care of the GUI), and possibly also allowing you to give up and maybe retry. BTW: I don't think every data source has to know and provide a ContentLength beforehand, so your approach with a pre-allocated byte array may fail for some sources. The alternative is to capture the data in a more dynamic structure (e.g. a list of arrays, each array holding one Read result) and then rearrange it if necessary. You could use this scheme when ContentLength returns abnormal values, such as zero. :)
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Please use <PRE> tags for code snippets, they improve readability.
CP Vanity has been updated to V2.4 -
As Bob already said, Read() is blocking. As the operation can be long-winding due to the amount of data, the lack of speed of the connection, or the potential failure of the transmission, you should be doing this on a background thread, allowing your app to continue its normal operation (at the bare minimum take care of the GUI), and possibly also allowing you to give up and maybe retry. BTW: I don't think every data source has to know and provide a ContentLength beforehand, so your approach with a pre-allocated byte array may fail for some sources. The alternative is to capture the data in a more dynamic structure (e.g. a list of arrays, each array holding one Read result) and then rearrange it if necessary. You could use this scheme when ContentLength returns abnormal values, such as zero. :)
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Please use <PRE> tags for code snippets, they improve readability.
CP Vanity has been updated to V2.4I already do the reading in the thread. The problem discovered with wifi internet connection type. Once the wifi is off Read blocks. How can I return from the background worker if it is blocked in the Read() method call? It was supposed to quit the thread if any error happen as it is with internet plugged into LAN. But wireless somehow blocks the method.
Чесноков
-
I send web requests and read data web response:
using (Stream stream = response.GetResponseStream())
{
Data = new byte[response.ContentLength];
int offset = 0;
int count = (int)response.ContentLength;
int nBytes = 0;
int nTotalBytes = 0;
while ((nBytes = stream.Read(Data, offset, count)) > 0)
{
offset += nBytes;
count -= nBytes;
nTotalBytes += nBytes;
}
}If internet connection is suddenyl down Read() function blocks forever. Is there a way to avoid it using the same Read() method?
Чесноков
The is no way for TCP to recognize that the other end no longer exists when it is waiting for a response. So the same is true for any protocol built on it. There might be situations where some sort of exception results. Maybe. For example I am not sure what the windows IP stack might do if you pull your network cable. But if you want to deal with all situations and not a just a few then you need to set up a timeout. Either via the protocol itself or via a secondary thread.
-
The is no way for TCP to recognize that the other end no longer exists when it is waiting for a response. So the same is true for any protocol built on it. There might be situations where some sort of exception results. Maybe. For example I am not sure what the windows IP stack might do if you pull your network cable. But if you want to deal with all situations and not a just a few then you need to set up a timeout. Either via the protocol itself or via a secondary thread.
jschell wrote:
But if you want to deal with all situations and not a just a few then you need to set up a timeout. Either via the protocol itself or via a secondary thread
I do set timeout in web request but I do not know how to set it for Read() operation as it just blocks.
Чесноков
-
I already do the reading in the thread. The problem discovered with wifi internet connection type. Once the wifi is off Read blocks. How can I return from the background worker if it is blocked in the Read() method call? It was supposed to quit the thread if any error happen as it is with internet plugged into LAN. But wireless somehow blocks the method.
Чесноков
Have you tried setting Stream.ReadTimeout? Not sure if it will help, but I think it should. BTW: don't read Stream.ContentLength twice, defensive programming dictates you read it once and store it in a local variable. If it were to change, for whatever reason, your code could be in a lot of trouble. :)
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Please use <PRE> tags for code snippets, they improve readability.
CP Vanity has been updated to V2.4 -
Have you tried setting Stream.ReadTimeout? Not sure if it will help, but I think it should. BTW: don't read Stream.ContentLength twice, defensive programming dictates you read it once and store it in a local variable. If it were to change, for whatever reason, your code could be in a lot of trouble. :)
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Please use <PRE> tags for code snippets, they improve readability.
CP Vanity has been updated to V2.4yes, thanks, that was the variable to set to, stream.TimeOut by default it is 5 minutes to read and write, quite large value. I would never discover the problem had it not been to wifi connection. It is surprising that ordinary landline disconnection immediatly result in Read() failure but with wifi it waits entire timeout.
Чесноков