如何阻止Python在调用需用户输入的C# DLL API时提前终止?
Python调用C# DLL时用户输入导致API中断的解决方案
问题背景
Python新手、C#中阶开发者,尝试通过pythonnet和clr调用C# DLL作为API,该DLL会启动外部程序,但DLL中的事件需要终端用户输入,每次输入后Python脚本会提前结束,导致API调用中断。
操作流程
- 通过pythonnet引入C# DLL:
import pythonnet import clr clr.AddReference("C:\path\to\dll\test.dll")
- 在Python中调用DLL函数:
from Namespace1 import Class1 my_obj = FunctionFromTestDLL()
- C# DLL调用外部程序的核心代码:
void FunctionFromTestDLL(out string userData) { MyAPI_ = new MyAPI.CompanyAPI(); }
- 最初用
input("Don't close this until Program finishes running!\n")临时阻止脚本退出,但DLL中存在多次触发的输入事件,输入后脚本仍会终止:
void UserInputEvent(out string userData) { System.Console.WriteLine("What is your data? \n"); userData = System.Console.ReadLine(); }
解决方案
方法1:循环等待外部程序完成
让Python脚本持续运行,通过DLL提供的状态判断外部程序是否结束,避免提前退出:
import pythonnet import clr import time clr.AddReference(r"C:\path\to\dll\test.dll") from Namespace1 import Class1 my_obj = Class1() my_obj.FunctionFromTestDLL() # 循环等待,需DLL提供判断外部程序运行状态的属性 while my_obj.IsExternalProgramRunning: time.sleep(1)
说明:需在C# DLL中新增IsExternalProgramRunning属性,用于标识外部程序是否仍在运行。
方法2:Python接管输入逻辑
修改C# DLL的事件处理逻辑,通过委托回调让Python处理输入,再将结果传回C#,支持多次输入:
- C# DLL中新增委托和事件:
public delegate string InputRequestHandler(string prompt); public event InputRequestHandler OnInputRequested; void UserInputEvent(out string userData) { if (OnInputRequested != null) { // 触发事件请求Python提供输入 userData = OnInputRequested("What is your data? \n"); } else { // 兼容原输入方式 System.Console.WriteLine("What is your data? \n"); userData = System.Console.ReadLine(); } }
- Python中订阅事件并处理输入:
import pythonnet import clr import time clr.AddReference(r"C:\path\to\dll\test.dll") from Namespace1 import Class1 def handle_input(prompt): print(prompt) return input() my_obj = Class1() # 绑定输入处理函数到C#事件 my_obj.OnInputRequested += handle_input my_obj.FunctionFromTestDLL() # 等待外部程序完成 while my_obj.IsExternalProgramRunning: time.sleep(1)
方法3:线程化运行API
如果无法修改C# DLL,可将API调用放入线程,主线程等待线程结束,保持脚本活跃:
import pythonnet import clr import threading clr.AddReference(r"C:\path\to\dll\test.dll") from Namespace1 import Class1 def run_api(): my_obj = Class1() my_obj.FunctionFromTestDLL() # 启动线程执行API调用 api_thread = threading.Thread(target=run_api) api_thread.start() # 主线程等待API线程结束 api_thread.join()
内容的提问来源于stack exchange,提问作者learningshark
相关产品推荐
相关产品推荐

