You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux树莓派下.NET5控制台程序开机自启自动退出如何解决?

报错根因

systemd开机自启的后台服务没有关联交互式控制台,Console.ReadKey() 方法依赖控制台输入流才能运行,无控制台环境下就会抛出你遇到的异常,你用这个方法的目的是阻塞主进程避免程序退出,只要替换成不依赖控制台的阻塞逻辑即可。

可用解决方案

方案1:极简适配,仅替换阻塞逻辑

直接把代码中的Console.ReadKey();替换为以下代码即可:

// 先引入命名空间
using System.Threading;

// 替换原Console.ReadKey()的位置
while (true)
{
    Thread.Sleep(Timeout.Infinite);
}

该逻辑不需要依赖任何控制台资源,后台运行时可以持续阻塞主进程,不会影响串口数据接收的事件回调。

方案2:规范服务化改造,支持优雅启停

如果需要适配后台服务的生命周期管理(比如收到停止指令时自动关闭串口、释放资源),可以用.NET通用主机托管程序:

  1. 先安装NuGet依赖包Microsoft.Extensions.Hosting
  2. 改写Main方法如下:
using Microsoft.Extensions.Hosting;
using System.Text;
using System.IO.Ports;
using System.Linq;

namespace ConsoleApp1
{
    internal class Program
    {
        private static SerialPort SP1 = new SerialPort("/dev/ttyUSB0", 57600, Parity.None, 8, StopBits.One);
        private static SerialPort SP2 = new SerialPort("/dev/ttyUSB1", 115200, Parity.None, 8, StopBits.One);        
        static void Main(string[] args)
        {
            var host = Host.CreateDefaultBuilder(args).Build();
            
            // 原有串口初始化逻辑
            SP1.DataReceived += SP_DataReceived;
            try
            {
                SP1.Open();
                SP2.Open();
                // 注册停止事件,退出时释放串口资源
                host.AppLifetime.ApplicationStopping.Register(() => {
                    SP1.Close();
                    SP1.Dispose();
                    SP2.Close();
                    SP2.Dispose();
                });
            }
            catch(Exception ex){ 
                Console.WriteLine(ex.Message);
                return;
            }                 
            Console.WriteLine("Started");
            
            host.Run();
        }
    
        static List<byte> ByteList = new List<byte>();
        // 原有SP_DataReceived方法保持不变
        private static void SP_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] buf = new byte[SP1.BytesToRead];
            Console.WriteLine("DATA RECEIVED!");
            SP1.Read(buf, 0, buf.Length);
            foreach (Byte b in buf)
            {
                ByteList.Add(b);
            }
            int StartIndex = -1;
            int EndIndex = -1;
            for (int i = 0; i < ByteList.Count; i++)
            {
                if (ByteList[i] == 2)
                {
                    StartIndex = i;
                }
                else if (ByteList[i] == 13 && ByteList.Count-1 > i && ByteList[i+1]==10)
                {
                    EndIndex = i + 1;
                    break;
                }
            }
            List<byte> NewByteList = new List<byte>();
            if (StartIndex != -1 && EndIndex != -1)
            {                
                for (int i = StartIndex+1; i <= EndIndex-2; i++)
                {
                    NewByteList.Add(ByteList[i]);
                }
            }
            ByteList.RemoveRange(StartIndex, EndIndex - StartIndex+1);
            var Result = Encoding.UTF8.GetString(NewByteList.ToArray()).Split(" ").Last().Replace(Environment.NewLine, "");            
            if (!string.IsNullOrEmpty(Result))
            {
                Console.WriteLine(Result);
                if (SP2.IsOpen)
                {
                    SP2.Write(Result+Environment.NewLine);
                }
                else {
                    Console.WriteLine("SP2 is not opened");
                }
            }
        }
    }
}
附加优化建议
  • 你配置的systemd服务单元可以添加Restart=always配置项,程序异常崩溃时会自动重启,提升服务稳定性
  • 不要使用/dev/ttyUSB0这类可变路径,建议用/dev/serial/by-id/目录下对应串口的固定唯一路径,避免重启或插拔设备后串口序号变化导致功能异常

内容的提问来源于stack exchange,提问作者Melon NG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 12:15:05