Python.NET:ASP.NET Core Razor页面中Py.GIL线程加载极慢问题
问题解决:ASP.NET Core Razor页面中Py.GIL()执行缓慢
问题原因
ASP.NET Core采用多线程线程池处理请求,而Python.Runtime的GIL管理依赖线程本地状态。控制台程序里PythonEngine.Initialize在主线程执行,后续GIL获取在同一线程无竞争;但Razor页面的请求由线程池工作线程处理,这些线程未预先初始化Python线程状态,首次获取GIL时需要创建并同步状态,加上潜在的GIL竞争,导致执行延迟。
解决方案
1. 优化全局PythonEngine初始化
在Program.cs中初始化时,添加skipFinalize参数,并在主线程预先获取一次GIL,完成线程状态初始化:
using Python.Runtime; var builder = WebApplication.CreateBuilder(args); // 配置Python运行时路径 Runtime.PythonDLL = "/Library/Frameworks/Python.framework/Versions/3.12/bin/python3"; // skipFinalize避免ASP.NET宿主生命周期冲突 PythonEngine.Initialize(skipFinalize: true); // 主线程预先获取并释放GIL,完成全局线程状态初始化 using (Py.GIL()) { // 空操作即可,目的是触发线程状态初始化 } // 后续Web应用配置 builder.Services.AddRazorPages(); var app = builder.Build(); // 中间件配置 app.MapRazorPages(); app.Run();
2. 在请求线程中管理Python状态
在Razor页面的OnGet方法中,确保当前线程的Python状态已正确初始化,避免首次获取GIL的延迟:
public void OnGet() { Console.WriteLine("On get"); // 检查并初始化当前线程的Python状态 if (!Runtime.PythonEngine.IsThreadInitialized) { Runtime.PythonEngine.InitializeThread(); } using (Py.GIL()) { Console.WriteLine("Reached line here"); } // 可选:若线程池线程复用,可在请求结束后清理线程状态 // Runtime.PythonEngine.ShutdownThread(); }
3. 禁止频繁Shutdown/Initialize
每次调用PythonEngine.Shutdown()再重新初始化会导致严重性能损耗和内存泄漏,务必避免。全局只需初始化一次PythonEngine,通过线程状态管理即可解决问题。
4. 版本兼容性检查
确保使用最新稳定版的Python.Runtime NuGet包,且与你的.NET Core版本(如.NET 6/7/8)兼容,旧版本在多线程Web场景下存在已知的GIL阻塞问题。
内容的提问来源于stack exchange,提问作者Kyle Zheng
相关产品推荐
相关产品推荐

