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

使用subprocess实现Python向C#传递Arduino数据时遇报错求助

解决Python与C#进程间通信及Arduino数据传递问题

错误原因分析

  • Python代码报错是因为subprocess.Popen.communicate()只能调用一次,调用后会关闭子进程的标准输入/输出流,循环中重复调用自然会触发输入发送失败的错误。
  • C#代码存在两个问题:构造函数里的死循环会阻塞UI线程,导致界面无响应;ReadToEnd()会等待输入流关闭才返回,无法实时接收Python传递的数据。

修正后的Python代码

直接通过子进程的stdin写入数据,避免使用communicate(),同时处理串口数据的编码和缓冲区刷新:

import serial
from subprocess import Popen, PIPE
import time

ser = serial.Serial('COM10', 9600, bytesize=8, timeout=1)

# 启动C#程序,无需shell=True(减少额外开销)
p = Popen(r"C:\Users\User\source\repos\Program\Program\bin\Debug\Program.exe", 
          stdout=PIPE, stdin=PIPE, stderr=PIPE, text=True)  # text=True让输入输出用字符串而非bytes

try:
    while True:
        data = ser.readline().decode('utf-8').strip()  # 解码串口数据并去除换行符
        if data:  # 跳过空数据
            p.stdin.write(data + '\n')  # 加换行符让C#可以逐行读取
            p.stdin.flush()  # 强制刷新缓冲区,确保数据立即发送
            print(f"发送数据: {data}")
        time.sleep(0.1)  # 避免循环过于频繁占用资源
except KeyboardInterrupt:
    # 程序终止时清理资源
    ser.close()
    p.stdin.close()
    p.terminate()

修正后的C#代码

使用后台线程实时读取标准输入,通过Invoke跨线程更新UI控件,避免阻塞界面:

using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace Program
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            // 启动后台线程读取输入
            Thread inputThread = new Thread(ReadInput);
            inputThread.IsBackground = true;  // 后台线程随程序关闭自动终止
            inputThread.Start();
        }

        private void ReadInput()
        {
            StreamReader reader = new StreamReader(Console.OpenStandardInput());
            while (true)
            {
                string line = reader.ReadLine();  // 逐行读取,实时响应数据
                if (!string.IsNullOrEmpty(line))
                {
                    // 跨线程更新Label(UI控件只能在创建它的线程操作)
                    label1.Invoke((MethodInvoker)delegate
                    {
                        label1.Text = line;
                    });
                }
            }
        }
    }
}

额外注意事项

  • 确保Arduino使用Serial.println()发送数据(默认会添加换行符,适配C#的ReadLine()),且数据为UTF-8编码。
  • Python中serial.Serial的timeout参数可以避免readline()长时间阻塞。
  • 如果需要处理C#程序的输出或错误,可以在Python中单独开启线程读取p.stdout和p.stderr,避免主循环阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 00:03:20