在Linux上作为服务运行时,防止.Net Core 5控制台应用程序终止的建议方法

Recommended way to prevent a .Net Core 5 console app from ending when run on Linux as a service(在Linux上作为服务运行时,防止.Net Core 5控制台应用程序终止的建议方法)
本文介绍了在Linux上作为服务运行时,防止.Net Core 5控制台应用程序终止的建议方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在Linux(Debian 10)上运行的.Net Core5控制台应用程序。基本结构如下:

class Program
{
    static async Task Main(string[] args)
    {
        await SetupStuffAsync();
        MonitorGpioService.Run();
        RunAScheduledServiceOnATimer();
        Console.ReadLine();
    }
}

基本上,它在Orange PI Zero(类似于覆盆子PI)上运行,等待GPIO引脚上的信号。当信号到达时,它读取串口几毫秒,将数据写入MariaDB数据库(使用EF Core),然后将数据发布到Web API。它还每隔5分钟运行一些计划的维护代码(使用System.Timers.Timer())。

此应用程序在无人值守的情况下运行--甚至没有屏幕--从Orange PI启动到关闭,它必须始终运行。

当我在开发期间手动运行应用程序时,Console.ReadLine()可以很好地阻止应用程序终止。 但现在我需要应用程序在Debian启动时自动运行,所以我做了以下操作:

sudo nano /etc/systemd/system/orangePi.service

[Unit]
Description=orangePi.service

[Service]
Type=simple 
ExecStart=/root/dotnet/dotnet sr/local/bin/orangePiService/orangePiService.dll
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target

这很管用-应用程序在启动时自动启动,但有一个问题。Console.ReadLine()将被完全忽略。它从字面上执行一切,然后结束。我认为这是有意义的,因为在本例中它不在控制台中运行。

我知道我可以,例如,在末尾放一个无限循环,以防止它结束:

class Program
{
    static async Task Main(string[] args)
    {
        await SetupStuffAsync();
        MonitorGpioService.Run();
        RunAScheduledServiceOnATimer();
        while (0 == 0) {};
    }
}

这个很管用,但我不喜欢。它不仅不美观,而且我可以想象它正在使用大量的CPU来运行该循环。

我可以这样做:

class Program
{
    static async Task Main(string[] args)
    {
        await SetupStuffAsync();
        MonitorGpioService.Run();
        RunAScheduledServiceOnATimer();
        while (0 == 0)
        {
            Thread.Sleep(int.MaxValue);
        };
    }
}

我想这会减轻CPU的负担,但我认为它阻塞了这个线程。这有问题吗?我知道这取决于代码的其余部分是什么样子,但这里要发布的代码相当多。我可以说的是,大多数操作都发生在Monitor GpioService.Run()中,我在下面以一种极其简化的格式发布了它:

using System.Device.Gpio;

public static class MonitorGpioService()
{
    static GpioController _controller;        

    public static void Run()        
    {
        _controller = new GpioController();
        _controller.RegisterCallbackForPinValueChangedEvent((int)Settings.GpioPin.Read, PinEventTypes.Rising, onSignalPinValueChangedEvent);
    }

    private static void onSignalPinValueChangedEvent(object sender, PinValueChangedEventArgs args)
    {
        string data = ReadSerialPortFor40ms();
        using (var context = new eballContext())
        {
            await _dbContext.Readings.AddRangeAsync(readings);
            await _dbContext.SaveChangesAsync();
        }
    }    
}    

我尽可能地使用等待,我认为它不会受到主线程被阻塞的影响。不过,我不确定当GPIO引脚状态改变时事件处理程序是否会触发。从我的测试来看,它似乎没有受到阻塞主线程的影响,但我不能确定...

总而言之(我为这篇文章的篇幅感到抱歉),我正在试图找出防止.Net Core控制台应用程序在Linux上作为服务运行时退出的最好方法。我最好的意思是尽可能少地消耗CPU,或者尽可能少地阻塞线程(假设这从一开始就是一个问题,考虑到我的大部分代码在定时器上运行或使用等待,我不是很确定)。

推荐答案

来自C# console program wait forever for event

如果使用异步Main方法,也可以使用await Task.Delay(-1);

Task.Delay()本身通常更优雅,因为它允许您传递取消令牌,从而在需要时允许正常关闭。

Thread.Sleep()也应该起作用,但不能取消。您可以使用Timeout.Infinite而不是While循环来暂停,而不会浪费任何周期

这篇关于在Linux上作为服务运行时,防止.Net Core 5控制台应用程序终止的建议方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)