Repository navigation
Using multiple proxies at once on the same stream #1423
|
Am I right that using multiple proxies on the same stream is not a supported scenario? I am getting "Unexpected Response" errors when I try to send an RPC from the second proxy - fyi, both proxies implement different interfaces. EDIT: Some extra information:In my application I have two interfaces: [JsonRpcContract(), GenerateShape(IncludeMethods = MethodShapeFlags.PublicInstance)]
public partial interface IInterfaceA : IDisposable
{
Task SomeMethodA();
}[JsonRpcContract(), GenerateShape(IncludeMethods = MethodShapeFlags.PublicInstance)]
public partial interface IInterfaceB : IDisposable
{
Task SomeMethodB();
}Then I initialize the server as follows (this is in a background service for a MAUI application: while (!stoppingToken.IsCancellationRequested)
{
using NamedPipeServerStream pipestream = NamedPipeFactory.CreateNamedPipeServer();
_logger.Information("Waiting for RPC client to connect...");
await pipestream.WaitForConnectionAsync(stoppingToken);
using JsonRpc rpc = new(pipestream)
{
CancelLocallyInvokedMethodsWhenConnectionIsClosed = true
};
rpc.Disconnected += (sender, e) =>
{
_logger.Information("RPC client disconnected. Message: {Message} Reason: {Reason}", e.Description, e.Reason);
};
#if DEBUG
rpc.TraceSource.Listeners.Add(new SerilogTraceListener.SerilogTraceListener(_logger));
#endif
rpc.AddLocalRpcTarget<IInterfaceA>(new AService(_logger), new()
{
ClientRequiresNamedArguments = true,
NotifyClientOfEvents = true,
});
rpc.AddLocalRpcTarget<IInterfaceB>(new BService(_logger), new()
{
ClientRequiresNamedArguments = true,
NotifyClientOfEvents = true,
});
rpc.StartListening();
_logger.Information("RPC client connected.");
await rpc.Completion;
_logger.Information("RPC client disconnected.");
}Now in my console app, I create two proxies as follows: var namedPipeClientStream = NamedPipeFactory.CreateNamedPipeClient(autoConnect: true);
var proxyA = JsonRPC.Attach<IInterfaceA>(namedPipeClientStream);
var proxyB = JsonRPC.Attach<IInterfaceB>(namedPipeClientStream);And have logic further on as: await proxyA.SomeMethodA(); // This one runs fine, no error
await proxyB.SomeMethodB(); // Error, no connectionIt seems after proxyA is called, the connection get's disconnected with the following logs: |
Replies: 3 comments 6 replies
|
Multiple proxies being used concurrently on the same connection is just fine. There must be some other explanation for the failures you're seeing. |
|
This is the bug: var proxyA = JsonRPC.Attach<IInterfaceA>(namedPipeClientStream);
var proxyB = JsonRPC.Attach<IInterfaceB>(namedPipeClientStream);You're attaching two distinct JsonRpc instances to the same stream. That's broken. Frankly I'm surprised it worked as far as it did. Instead you have a few options:
|
|
The issue happens because calling the static The correct way to use multiple proxies over a single stream is to create one var namedPipeClientStream = NamedPipeFactory.CreateNamedPipeClient(autoConnect: true);
// 1. Create a single JsonRpc connection
var jsonRpc = new JsonRpc(namedPipeClientStream);
// 2. Attach multiple proxies to the same connection
var proxyA = jsonRpc.Attach<IInterfaceA>();
var proxyB = jsonRpc.Attach<IInterfaceB>();
// 3. Start listening on the connection
jsonRpc.StartListening();
// 4. Now both proxies work concurrently and thread-safely
await proxyA.SomeMethodA();
await proxyB.SomeMethodB(); |
The issue happens because calling the static
JsonRpc.Attach<T>(stream)twice creates two separateJsonRpcinstances competing over the same stream.The correct way to use multiple proxies over a single stream is to create one
JsonRpcinstance first, attach your interfaces, and then callStartListening():