Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.InvalidOperationException ("Concurrent reads or writes are not supported.") #170

Open
Xhanti opened this issue Dec 30, 2024 · 1 comment

Comments

@Xhanti
Copy link

Xhanti commented Dec 30, 2024

Hi,

When trying to use the IConnectionFactory in parallel like this:

var serviceCollection = new ServiceCollection();
var serviceProvider = serviceCollection.BuildServiceProvider();
var client = new ClientBuilder(serviceProvider)
                       .UseSockets()                           
                       .Build();
await using (var connection = await client.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 5000)))
{
    await Parallel.ForAsync(0, 10, options, async (i, ct) =>
    {
        var request = new HttpRequestMessage(HttpMethod.Get, "/");
        request.Headers.Host = "localhost";
        var httpProtocol = new HttpClientProtocol(connection);
        var response = await httpProtocol.SendAsync(request);
    });
}

I get System.InvalidOperationException saying "Concurrent reads or writes are not supported."
Digging around I see this is inside system.io.pipelines:

   at Bedrock.Framework.Protocols.HttpClientProtocol.<SendAsync>d__4.MoveNext()
   at Bedrock.Framework.Protocols.HttpClientProtocol.<SendAsync>d__4.MoveNext()
   at Bedrock.Framework.Protocols.HttpClientProtocol.<SendAsync>d__4.MoveNext()
   at System.IO.Pipelines.Pipe.GetReadResult(ReadResult& result) in System.IO.Pipelines\Pipe.cs:line 901
   at System.IO.Pipelines.Pipe.GetReadAsyncResult() in System.IO.Pipelines\Pipe.cs:line 885
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
   at Bedrock.Framework.Protocols.ProtocolReader.<ContinueDoAsyncRead>d__14`1.MoveNext()
   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
   at Program.<>c__DisplayClass0_0.<<<Main>$>b__0>d.MoveNext() in C:\Working\Raikiri\Raikiri\Program.cs:line 41
   at Bedrock.Framework.Protocols.HttpClientProtocol.<SendAsync>d__4.MoveNext()
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
--- End of stack trace from previous location ---
   at Bedrock.Framework.Protocols.HttpClientProtocol.<SendAsync>d__4.MoveNext()
   at System.Threading.Tasks.Parallel.<>c__49`1.<<ForAsync>b__49_0>d.MoveNext()
   at System.Threading.Tasks.Parallel.<>c__49`1.<<ForAsync>b__49_0>d.MoveNext()
image

Is this expected behavior?
For a bit of colour, I'm experimenting with using this framework to put something like https://github.com/codesenberg/bombardier together in .NET

@davidfowl
Copy link
Owner

Yes, its expected. A real http client needs to implement a connection pool to make sure there are no concurrent writes to the same socket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants