C# .NET Core 1.1控制台应用程序在Ubuntu 16.04上始终作为systemd服务退出/崩溃

C# .NET Core 1.1控制台应用程序在Ubuntu 16.04上始终作为systemd服务退出/崩溃,c#,linux,.net-core,daemon,systemd,C#,Linux,.net Core,Daemon,Systemd,我正在尝试创建一个简单的echo服务,它与systemdinit系统一起工作。一切正常,它甚至在快速部署后启动,但当我试图通过systemctl status命令了解其状态时,它很快退出(或崩溃) 逻辑很简单,这里我提供以下来源: Program.cs using System; using System.Threading.Tasks; namespace hw { class Program { private const int delay = 1000;

我正在尝试创建一个简单的echo服务,它与
systemd
init系统一起工作。一切正常,它甚至在快速部署后启动,但当我试图通过
systemctl status
命令了解其状态时,它很快退出(或崩溃)

逻辑很简单,这里我提供以下来源:

Program.cs

using System;
using System.Threading.Tasks;

namespace hw
{
    class Program
    {
        private const int delay = 1000;
        private static Random random = new Random();

        static async Task Handle()
        {
            Console.WriteLine($"tick tack... {random.Next()}");
            await Task.Delay(delay);
            await Handle();
        }

        static void Main(string[] args)
        {
            Task.Factory.StartNew(async() => await Handle());
            Console.ReadLine();
        }
    }
}
hw.service(systemd配置文件)

帮助脚本,init.sh(如果要在本地系统上试用,也可以使用
chmod+x init.sh
):

日志:

  • 构建/部署:
  • journalctl-fu硬件服务
  • 在首次部署之后,从系统控制状态硬件服务开始:
我在等什么

我希望我的服务运行时与其他我的服务(ASP.NET Core)运行时一样(处于活动/绿色状态),即
systemd
服务。至于ASP.NET核心项目,没有问题,至于简单的控制台-它们是

如何解决我的问题


感谢由于Evk建议使用
ManualResetEvent
,我做了下一步:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace hw
{
    class Program
    {
        private const int delay = 1000;
        private static Random random = new Random();
        private static ManualResetEvent resetEvent = new ManualResetEvent(false);

        static async Task Handle()
        {
            Console.WriteLine($"tick tack... {random.Next()}");
            await Task.Delay(delay);
            await Handle();
        }

        static void Main(string[] args)
        {
            Task.Factory.StartNew(async() => await Handle());
            Console.CancelKeyPress += (sender, eventArgs) => 
            {
                // Cancel the cancellation to allow the program to shutdown cleanly.
                eventArgs.Cancel = true;
                resetEvent.Set();
            };
            resetEvent.WaitOne();
        }
    }
}

现在一切正常&服务不会停止/崩溃。

但您正在非交互模式下运行,所以我认为Console.ReadLine不工作。请尝试将Console.CancelKeyPress事件与ManualResetEvent结合使用。@Evk非常感谢,我已经完成了您的建议,我的服务正在运行。我之前不知道交互模式。另外,我注意到,.NETCore的当前版本没有
Environment.UserInteractive
属性。还有,这里有一些有趣的信息:,再次非常感谢。如果你愿意,你可以写一个关于这个问题的答案,我会接受的。很高兴它有帮助,但至于写答案,我只是不确定确切的原因,我还没有太多的经验与.net核心。例如,在full.NET中,我记得Console.ReadLine仍将在非交互模式下工作(将阻塞),Console.ReadKey将引发异常。无论如何,如果您不需要任何输入(作为服务运行),最好不要使用Console.ReadLine等方法。您可以替换
Task.Factory.StartNew(async()=>await Handle())public static class TaskExtensions{public static void Forget(this Task Task){}}
来阐明您的意图并删除该警告(当然,忽略任务通常不是一个好主意,因为它可能会引发您无法观察到的异常)@Evk非常感谢:)
dotnet build
dotnet publish

echo "\nPreparing binaries for the service directory:\n"
rm -rf /var/netcore/hw
mkdir /var/netcore /var/netcore/hw
cp -R bin/Debug/netcoreapp1.1/publish/* /var/netcore/hw
ls -la /var/netcore/hw

echo "\nInitializing the systemd service:"
systemctl stop hw.service
rm /etc/systemd/system/hw.service
cp hw.service /etc/systemd/system/hw.service
systemctl daemon-reload
systemctl enable hw.service
systemctl start hw.service
systemctl status hw.service
using System;
using System.Threading;
using System.Threading.Tasks;

namespace hw
{
    class Program
    {
        private const int delay = 1000;
        private static Random random = new Random();
        private static ManualResetEvent resetEvent = new ManualResetEvent(false);

        static async Task Handle()
        {
            Console.WriteLine($"tick tack... {random.Next()}");
            await Task.Delay(delay);
            await Handle();
        }

        static void Main(string[] args)
        {
            Task.Factory.StartNew(async() => await Handle());
            Console.CancelKeyPress += (sender, eventArgs) => 
            {
                // Cancel the cancellation to allow the program to shutdown cleanly.
                eventArgs.Cancel = true;
                resetEvent.Set();
            };
            resetEvent.WaitOne();
        }
    }
}