내가 다음 C# 기능을 작성했습니다 차단 :기능 읽기 라인은
static string ReadLineCRLF(System.IO.Stream Stream, ref byte[] sharedBuffer, int bufferSize = 1024)
{
StringBuilder responseString = new StringBuilder("");
string returnString = "";
byte[] buffer = new byte[bufferSize];
bool stopreading = false;
bool firstexecution = true;
while (!stopreading)
{
int readBytes;
if (firstexecution && sharedBuffer.Length > 0)
{
readBytes = sharedBuffer.Length;
sharedBuffer.CopyTo(buffer, 0);
}
else
{
readBytes = Stream.Read(buffer, 0, bufferSize); //BLOCKING HERE
}
firstexecution = false;
if (readBytes > 0)
{
int crIndex = Array.IndexOf(buffer, (byte)13); //13 = ASCII value for a carriage return
if (crIndex > -1 && Array.IndexOf(buffer, (byte)10, crIndex + 1) == crIndex + 1) //10 = ASCII value for line feed
{
stopreading = true;
sharedBuffer = readBytes - crIndex - 2 > 0 ? ArraySlice<byte>(buffer, crIndex+2, readBytes-crIndex-2) : new byte[] { };
readBytes = crIndex;
}
if (readBytes > 0)
{
responseString.Append(System.Text.Encoding.ASCII.GetString(buffer, 0, readBytes));
}
if (stopreading)
{
returnString = responseString.ToString();
}
}
if (!stopreading && readBytes <= 0)
{
returnString = null;
stopreading = true;
sharedBuffer = new byte[] { };
}
}
return returnString;
}
이 기능은 내 스택 탐색기에 따라 컴퓨터의 성능을 많이 사용 readBytes = Stream.Read(buffer, 0, bufferSize);
에 차단하고 있습니다. 이 함수가해야하는 유일한 일은 CRLF ("\ r \ n")로 끝나는 스트림에서 한 행을 읽는 것입니다.
MSDNStream.Read
에 따르면 less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
을 반환하며 대개 CPU 성능을 차단하고 사용하지 않아야합니다. The implementation will block until at least one byte of data can be read, in the event that no data is available. Read returns 0 only when there is no more data in the stream and no more is expected (such as a closed socket or end of file)
.
그렇다면 CLR 스택 탐색기에 따르면 성능이 최대 70 %까지 올라간 이유는 무엇입니까? 논리적 인 실수는 보이지 않습니다. 몇 바이트를받을 때까지 기다려야한다고 생각합니다. 또한이 동작은 항상 발생하지는 않지만 Windows 서버에서 응용 프로그램을 실행 한 후 1-2 일이 지나간 것으로 보입니다.
추가 설명 : 청크를 사용하여 바이트를 읽으므로 너무 많은 바이트를 읽고 버퍼에 저장할 수 있습니다. 따라서 공유 버퍼를 사용하여 다음 줄을 읽는 데 다시 사용할 수 있습니다. 일단 라인이 완전히 읽혀지면 버퍼에서 그것을 제거합니다.
ArraySlice 기능은 다음과 같습니다 :
public static T[] ArraySlice<T>(T[] data, int index, int length)
{
T[] result = new T[length];
Array.Copy(data, index, result, 0, length);
return result;
}
왜 단순히 StreamReader를 사용하지 않습니까? 필요한만큼 줄을 줄 것입니다. –
라인은 정확히 CRLF로 끝나야하기 때문에. 'StreamReader.ReadLine'은 간단한 CR과 LF도 허용합니다. 이것은 일부 RFC 사양 때문입니다. –