Currently I have a working implementation by using an SSL Stream, wrapped in a bufferedstream, and just calling read/write on the stream using byte arrays.
I want to make this faster, and from some reading it looks like System.IO.Pipelines
are the way to go for high performance IO.
A lot of articles/demos I've read only demonstrate code using a socket directly - Which doesn't seem to work with me since I'm using SSL.
I've found some extensions to get a pipereader/writer from a stream > Stream.UsePipeReader()
or Stream.UsePipeWriter()
so I've tried calling
SSLStream.UsePipeReader()
However I consistently get the error:
System.NotSupportedException : The ReadAsync method cannot be called when another read operation is pending.
at System.Net.Security.SslStreamInternal.ReadAsyncInternal[TReadAdapter](TReadAdapter adapter, Memory`1 buffer)
at Nerdbank.Streams.PipeExtensions.<>c__DisplayClass5_0.<<UsePipeReader>b__1>d.MoveNext() in D:\a\1\s\src\Nerdbank.Streams\PipeExtensions.cs:line 92
--- End of stack trace from previous location where exception was thrown ---
at System.IO.Pipelines.PipeCompletion.ThrowLatchedException()
at System.IO.Pipelines.Pipe.GetReadResult(ReadResult& result)
at System.IO.Pipelines.Pipe.GetReadAsyncResult()
My code to read from the pipe is:
private async Task<string> ReadAsync(PipeReader reader)
{
var stringBuilder = new StringBuilder();
while (true)
{
var result = await reader.ReadAsync();
var buffer = result.Buffer;
SequencePosition? position;
do
{
// Look for a EOL in the buffer
position = buffer.PositionOf((byte) '\n');
if (position != null)
{
// Process the line
ProcessLine(buffer.Slice(0, position.Value), stringBuilder);
buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
}
} while (position != null);
reader.AdvanceTo(buffer.Start, buffer.End);
if (result.IsCompleted)
{
reader.Complete();
break;
}
}
return stringBuilder.ToString();
}
It is not being called by any other threads as I've tested it with a lock around it. And I'm only doing a single call at a time for testing purposes.
Can anyone tell me what I'm doing wrong?
Thanks!
I believe I might know the answer.
Your problem might be in this line:
var result = await reader.ReadAsync();
You see, await block the execution only in the Send method, but meanwhile the code in the caller continues to execute even if the ReadAsync()
has not completed yet.
Now if the Send method is called again before the ReadAsync()
has completed you will get the exception that you have posted since SslStream does not allow multiple read/write operations and the code that you have posted does not prevent this from happening.
You need to write your own safety fail mechanism for this case, In order to avoid the second call before the completion of the first one.
Since you are using a loop here:
while (true)
{
//rest of code...
}
I believe this is where you should tend your problem. You are reaching the second iteration while the first one is not completed yet, thus resulting in:
System.NotSupportedException
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With