Console.Error.WriteLineAsync() vs Console.WriteLine,有何不同。为什么后面会抛出异常?

Console.Error.WriteLineAsync() vs Console.WriteLine, what is the difference. Why does the later throw exception?

提问人:VivekDev 提问时间:8/4/2023 最后编辑:Guru StronVivekDev 更新时间:8/4/2023 访问量:100

问:

我正在尝试了解 StreamJsonRpc 并从这里运行一个示例。

我在这里创建了一个调低的示例。它包含服务器和客户端,并通过 StreamJsonRpc 进行通信。

在服务器中,当我使用 Console.WriteLine 时,它会抛出异常。当我恢复使用 await Console.Error.WriteLineAsync() 时,它运行良好。

Exception is throw

为什么?看起来与我缺少的 await 异步有关。

以下方法有效。

private static async Task RespondToRpcRequestsUsingConsoleErrorAsync(Stream stream, int clientId)
{
    await Console.Error.WriteLineAsync($"Connection request #{clientId} received. Spinning off an async Task to cater to requests.");
    var jsonRpc = JsonRpc.Attach(stream, new Server());
    await Console.Error.WriteLineAsync($"JSON-RPC listener attached to #{clientId}. Waiting for requests...");
    await jsonRpc.Completion;
    await Console.Error.WriteLineAsync($"Connection #{clientId} terminated.");
}

以下引发异常。您可以在下面的 Console.WriteLine() 中看到替换了上面的 await Console.Error.WriteLineAsync()。

private static async Task RespondToRpcRequestsUsingConsoleAsync(Stream stream, int clientId)
{
    Console.WriteLine($"Connection request #{clientId} received. Spinning off an async Task to cater to requests.");
    var jsonRpc = JsonRpc.Attach(stream, new Server());
    Console.WriteLine($"JSON-RPC listener attached to #{clientId}. Waiting for requests...");
    await jsonRpc.Completion;
    Console.WriteLine($"Connection #{clientId} terminated.");
}

我尝试使用jsonRpc.Completion.Wait()jsonRpc.Completion.GetAwaiter()。GetResult();如下所示,但没有成功。

private static void RespondToRpcRequestsUsingConsoleWithWait(Stream stream, int clientId)
{
    Console.WriteLine($"Connection request #{clientId} received. Spinning off an async Task to cater to requests.");
    var jsonRpc = JsonRpc.Attach(stream, new Server());
    Console.WriteLine($"JSON-RPC listener attached to #{clientId}. Waiting for requests...");
    jsonRpc.Completion.Wait(); // SEE HERE
    Console.WriteLine($"Connection #{clientId} terminated.");
}

private static void RespondToRpcRequestsUsingConsoleWithAwaiterAndResult(Stream stream, int clientId)
{
    Console.WriteLine($"Connection request #{clientId} received. Spinning off an async Task to cater to requests.");
    var jsonRpc = JsonRpc.Attach(stream, new Server());
    Console.WriteLine($"JSON-RPC listener attached to #{clientId}. Waiting for requests...");
    jsonRpc.Completion.GetAwaiter().GetResult(); // SEE HERE
    Console.WriteLine($"Connection #{clientId} terminated.");
}

如何运行该示例。

  1. 只需在 Visual Studio 中打开,将客户端设置为启动项目,然后按 F5 即可。
  2. 使用命令行,cd 进入客户端项目并运行它。
cd JsonRpcStdIoClient
dotnet run --project ./JsonRpcStdIoClient.csproj
C# 异步 .net-core async-await json-rpc

评论


答:

3赞 Guru Stron 8/4/2023 #1

这与.您正在使用 / 在进程之间进行通信,请写入 。因此,当您在服务器上调用它时,至少从角度来看,它会向通信通道发送一些随机数据,而这些数据似乎无法处理,因此结果。 另一方面,写入标准错误流,因此不会影响通信通道。asyncStandardInputStandardOutputConsole.WriteLineStandardOutputJsonRpcJsonRpcConsole.Error

作为实验,删除服务器中的所有内容,并为客户端添加对双工流的监视:Console.WriteLine

// setup process and stdioStream

var monitoringStream = new MonitoringStream(stdioStream);
var inwr = new MemoryStream();
var outwr = new MemoryStream();
monitoringStream.DidRead += (s, e) => inwr.Write(e);  
monitoringStream.DidWrite += (s, e) => outwr.Write(e);

try
{
    await ActAsRpcClientAsync(monitoringStream);
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}

Console.WriteLine("----\nIn:\n");
Console.WriteLine(Encoding.UTF8.GetString(inwr.ToArray()));
Console.WriteLine("----\nOut:\n");
Console.WriteLine(Encoding.UTF8.GetString(outwr.ToArray()));

这导致类似的东西

Connected. Sending request...
Received request: 3 + 5
3 + 5 = 8
----
In:

Content-Length: 35

{"jsonrpc":"2.0","id":2,"result":8}
----
Out:

Content-Length: 54

{"jsonrpc":"2.0","id":2,"method":"Add","params":[3,5]}