.NET Core Console.ReadLine() 在 Linux 中执行的奇怪问题
🏷️ .NET Core
Console.ReadLine()
在 Windows 中执行时会等待输入回车才会继续执行,但是发布到 Docker 上之后没有得到预想中的结果,程序运行到这里直接结束了。
示例代码如下:
static void Main(string[] args)
{
Task.Run(() =>
{
// do somethind
Thread.Sleep(Timeout.Infinite);
});
Console.WriteLine("Press [enter] to exit.");
Console.ReadLine();
Environment.Exit(-1);
}
不确定是因为什么原因导致的输入了回车主线程也没有退出 因为启动的线程中使用了 ,所以在程序的最后通过 Thread.Sleep(Timeout.Infinite);
Environment.Exit(-1);
来退出。
怀疑是因为新线程中创建了 RabbitMQ 的订阅导致的。(不明白为什么后台线程会阻止主线程的结束)
如果没有该行代码的话,在 windows 中即使输入了回车程序也不会退出。怀疑是因为 Thread.Sleep(Timeout.Infinite);
导致的。虽然是在后台线程中执行的 Sleep,但是貌似会阻塞主线程的退出(这里不太确定,但从效果上来看是这样的)。
删除 Environment.Exit(-1);
之后在 Linux 上运行仍然直接退出了,然后就只能怀疑是 Console.ReadLine()
出错,从而导致主线程退出。可惜添加了 Try Catch 处理仍然没有打印出任何异常信息(这个以后有时间再做些测试)。
暂时的对策是在 Main 方法的最后使用 Thread.Sleep
来阻止主线程退出。
static void Main(string[] args)
{
Task.Run(() =>
{
// do somethind
Thread.Sleep(Timeout.Infinite);
});
Console.WriteLine("Close console to exit.");
Thread.Sleep(Timeout.Infinite);
}
2019/6/27 追记
今天测试了一下 Console.ReadLine()
、Console.ReadKey()
、Console.Read()
在 linux 中执行的效果。
测试环境是在 docker 中执行的,其 Dockerfile 的内容如下(基于 microsoft/dotnet:2.1-runtime 镜像):
FROM microsoft/dotnet:2.1-runtime AS base
WORKDIR /app
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY ReadLineTest17/ReadLineTest17.csproj ReadLineTest17/
RUN dotnet restore ReadLineTest17/ReadLineTest17.csproj
COPY . .
WORKDIR /src/ReadLineTest17
RUN dotnet build ReadLineTest17.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish ReadLineTest17.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "ReadLineTest17.dll"]
如下是测试代码及各自在 docker 中的执行结果。
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.ReadLine();
Console.WriteLine("Bye Bye !");
}
Console.ReadLine();
没有报错,也没有任何效果。
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.ReadKey();
Console.WriteLine("Bye Bye 1 !");
}
Console.ReadKey();
引发了异常:
Unhandled Exception: System.InvalidOperationException: Cannot read keys when either application does not have a console or when console input has been redirected. Try Console.Read.
at System.ConsolePal.ReadKey(Boolean intercept)
at ReadLineTest17.Program.Main(String[] args) in /src/ReadLineTest17/Program.cs:line 10
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.Read();
Console.WriteLine("Bye Bye 2 !");
}
根据上一个异常中的提示,改用了 Console.Read();
方法,其和 Console.ReadLine();
类似,没有任何效果。
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Thread.Sleep(Timeout.Infinite);
Console.WriteLine("Bye Bye 3 !");
}
这个是之前的对策,可以实现阻止主线程退出的效果。
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.ReadLine();
Console.ReadLine();
Console.ReadLine();
Console.ReadLine();
Console.ReadLine();
Console.ReadLine();
Console.ReadLine();
Console.ReadLine();
Console.ReadLine();
Console.ReadLine();
Console.WriteLine("Bye Bye 4 !");
}
=.=||| 执行再多遍 Console.ReadLine();
也没有任何效果。
测试了 C# Mono Console.ReadLine quitting 中的回答:
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.WriteLine(readKeey());
Console.WriteLine("Bye Bye 5 !");
}
private static string readKeey()
{
ConsoleKeyInfo cki;
Console.TreatControlCAsInput = true;
string temp = "";
do
{
cki = Console.ReadKey();
temp = temp + cki.KeyChar;
} while (cki.Key != ConsoleKey.Enter);
return temp;
}
跟上面的 Console.ReadKey();
同样的结果,引发了 System.InvalidOperationException 异常。