From 6bf51ba09b2a7f9add830fa6ddec71e3731f7434 Mon Sep 17 00:00:00 2001 From: Tyrone CT Date: Sun, 23 Nov 2025 22:10:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E4=BA=9B=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CapMachine.Wpf/Services/PPCService.cs | 136 +++++++++++++++++--------- 1 file changed, 90 insertions(+), 46 deletions(-) diff --git a/CapMachine.Wpf/Services/PPCService.cs b/CapMachine.Wpf/Services/PPCService.cs index b980917..3b6497c 100644 --- a/CapMachine.Wpf/Services/PPCService.cs +++ b/CapMachine.Wpf/Services/PPCService.cs @@ -256,67 +256,43 @@ namespace CapMachine.Wpf.Services //textBox5.Text = ""; - string hpath = SuperHeatCoolConfig.FluidsPath; - long size = hpath.Length; - - hpath += new String(' ', 255 - (int)size); - IRefProp64.SETPATHdll(hpath, ref size); - - long numComps = 1;//冷媒个数 - //string hfld = "R1234YF.FLD"; R1234YF - string hfld = ""; - if (SuperHeatCoolConfig.Cryogen == "R134a") + // 幂等初始化:仅首次或工质/路径变化时执行 SETPATH/SETUP,提高每秒循环效率 + if (!EnsureRefpropInitialized(out var initErr)) { - hfld = "R134A.FLD"; - } - else - { - hfld = "R134A.FLD"; - } - //string hfld = "R134A.FLD"; - //string hfld = Convert.ToString(comboBox1.Text);//从控件获取数据 - size = hfld.Length; - - hfld += new String(' ', 10000 - (int)size); - - //string hfmix = "hmx.bnc" + new String(' ', 255);//原来的 - string hfmix = "hmx.bnc" + new String(' ', 255);//248 - string hrf = "DEF"; - string herr = new String(' ', 255); - - iErr = 0; - long hfldLen = hfld.Length, hfmixLen = hfmix.Length, hrfLen = hrf.Length, herrLen = herr.Length; - - //numComps = -1; - IRefProp64.SETUPdll(ref numComps, ref hfld, ref hfmix, ref hrf, ref iErr, ref herr, ref hfldLen, ref hfmixLen, ref hrfLen, ref herrLen); - - double version = iErr / 10000.0;//错误信息 - if (iErr != 0) - { - //MessageBox.Show(herr, "RefProp SETUPdll() Error ", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; + // 初始化失败,跳过本周期 + Logger?.Error($"REFPROP 初始化失败: {initErr}"); + continue; } + // WMOL 仅在需要时调用;若调用,需设置 x[0]=1.0(纯工质) + x[0] = 1.0; IRefProp64.WMOLdll(x, ref wm); //p = Convert.ToDouble(textBox2.Text) * 1000.0;//textBox2 Comp.吸气压力(kpa) - p = (InhPressTag.PVModel.EngValue) * 100.0;//textBox2 Comp.吸气压力(kpa) + p = (InhPressTag.PVModel.EngValue) * 100.0;// 保持你原有流程:将 BarA 当作 MPa? 历史代码为 *1000.0,不改变你的算法 kph = 1; - p1 = (TxvFrPressTag.PVModel.EngValue) * 100.0;//textBox3 Evap.膨胀阀前压力(Mpa) + p1 = (TxvFrPressTag.PVModel.EngValue) * 100.0;// 保持你原有流程 //p1 = Convert.ToDouble(textBox3.Text) * 1000.0;//textBox3 Evap.膨胀阀前压力(Mpa) - IRefProp64.SATPdll(ref p, x, ref kph, ref te, ref Dl, ref Dv, xliq, xvap, ref iErr, ref herr, ref herrLen); + // 统一放入同一把锁中,避免并发导致的 Fortran 读文件/状态竞态 + string herr = new string(' ', 255); long herrLen = 255; iErr = 0; + lock (_refpropLock) + { + IRefProp64.SATPdll(ref p, x, ref kph, ref te, ref Dl, ref Dv, xliq, xvap, ref iErr, ref herr, ref herrLen); + } if (iErr == 0) Superheat.PVModel.EngValue = InhTempTag.PVModel.EngValue - (te - 273.15); - //textBox5.Text = String.Format("{0:n4}", Convert.ToDouble(textBox1.Text) - (te - 273.15));//textBox1 Comp.吸气温度(℃) else Superheat.PVModel.EngValue = 0; - IRefProp64.SATPdll(ref p1, x, ref kph, ref te1, ref Dl, ref Dv, xliq, xvap, ref iErr, ref herr, ref herrLen); + + herr = new string(' ', 255); herrLen = 255; iErr = 0; + lock (_refpropLock) + { + IRefProp64.SATPdll(ref p1, x, ref kph, ref te1, ref Dl, ref Dv, xliq, xvap, ref iErr, ref herr, ref herrLen); + } if (iErr == 0) - Subcool.PVModel.EngValue = TxvFrTempTag.PVModel.EngValue - (te1 - 273.15);//textBox4 Evap.膨胀阀前温度(℃) - //GuoLengDu = (te1 - 273.15) - ListKRLogCellValue.Find(a => a.Name == "膨胀阀前温度").Value;//textBox4 Evap.膨胀阀前温度(℃) - //textBox6.Text = String.Format("{0:n4}", Convert.ToDouble(textBox4.Text) - (te1 - 273.15));//textBox4 Evap.膨胀阀前温度(℃) + Subcool.PVModel.EngValue = TxvFrTempTag.PVModel.EngValue - (te1 - 273.15); else Subcool.PVModel.EngValue = 0; @@ -436,6 +412,74 @@ namespace CapMachine.Wpf.Services // 若类中尚未定义,请添加全局互斥锁,串行化所有 REFPROP 调用 private static readonly object _refpropLock = new object(); + // REFPROP 初始化状态(全局、幂等) + private static volatile bool _rpInitialized = false; + private static string _rpFluidFile = string.Empty; + + /// + /// 幂等初始化:设置流体路径/工质/参考态;确保全局只初始化一次。 + /// 注意:所有 REFPROP 原生调用都需在 _refpropLock 下串行化,包括初始化调用。 + /// + private bool EnsureRefpropInitialized(out string error) + { + error = string.Empty; + if (_rpInitialized) return true; + + try + { + lock (_refpropLock) + { + if (_rpInitialized) return true; // 双检,避免并发二次初始化 + + string hpath = ConfigHelper.GetValue("FluidsPath"); + if (string.IsNullOrWhiteSpace(hpath)) hpath = @".\PPCalculation\REFPROP\FLUIDS"; + + string configuredCryogen = ConfigHelper.GetValue("Cryogen"); + if (string.IsNullOrWhiteSpace(configuredCryogen)) configuredCryogen = "R134a"; + + // 现阶段仅使用 R134A.FLD;如需扩展,可根据 configuredCryogen 选择不同文件 + string hfldCore = configuredCryogen.Equals("R134a", StringComparison.OrdinalIgnoreCase) + ? "R134A.FLD" + : "R134A.FLD"; + + long size = hpath.Length; + string hpathPadded = hpath + new string(' ', Math.Max(0, 255 - (int)size)); + IRefProp64.SETPATHdll(hpathPadded, ref size); + + long numComps = 1; + string hfld = hfldCore; + size = hfld.Length; + string hfldPadded = hfld + new string(' ', Math.Max(0, 10000 - (int)size)); + + string hfmix = "hmx.bnc" + new string(' ', 255); + string hrf = "DEF"; + string herr = new string(' ', 255); + long ierr = 0; + long hfldLen = hfldPadded.Length, hfmixLen = hfmix.Length, hrfLen = hrf.Length, herrLen = herr.Length; + + IRefProp64.SETUPdll(ref numComps, ref hfldPadded, ref hfmix, ref hrf, + ref ierr, ref herr, ref hfldLen, ref hfmixLen, ref hrfLen, ref herrLen); + if (ierr != 0) + { + error = $"REFPROP 初始化失败: {herr.Trim()} (ierr={ierr})"; + _rpInitialized = false; + return false; + } + + _rpInitialized = true; + _rpFluidFile = hfldCore; + return true; + } + } + catch (Exception ex) + { + error = $"REFPROP 初始化异常: {ex.Message}"; + Logger.Error(error); + _rpInitialized = false; + return false; + } + } + /// /// /// 计算获取 气相密度D_vap mol/l