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

在C#控制台应用中使用cwbx调用iSeries AS400程序性能缓慢求助

在C#控制台/Windows服务中使用cwbx调用AS400程序参数构建缓慢的问题及解决方法

问题描述

我在C#控制台应用(或Windows服务)中使用cwbx库(IBM i Access for Windows ActiveX自动化对象)调用iSeries AS400程序时,遇到了严重的性能问题:

  • 待传递的参数结构复杂:包含3个独立cwbx.Structure、5个结构数组(元素数分别为30、300、10、20、10,每个元素含不同cwbx.StructureField),总计373个结构对象+5个标识数组的伪结构
  • 性能差异显著:WPF应用中总耗时仅0.4230891秒,控制台应用耗时达2.5116918秒
  • 耗时差异点:program.Call(parameters)阶段耗时一致,问题集中在输入参数的构建与赋值环节

疑问:cwbx是否依赖窗口句柄才导致控制台应用运行缓慢?有没有可行的解决办法?

附示例代码:

var system = new AS400System();
system.Define("AS400");
system.UserID = "USER";
system.Password = "PASSWORD";
system.IPAddress = "192.168.1.55";
system.PromptMode = cwbcoPromptModeEnum.cwbcoPromptNever;
system.Signon();
system.Connect(cwbcoServiceEnum.cwbcoServiceRemoteCmd);
try
{
    // Check the connection
    if (system.IsConnected(cwbcoServiceEnum.cwbcoServiceRemoteCmd) == 1)
    {
        var program = new Program();
        program.LibraryName = "*LIBL";
        program.ProgramName = "BW6IF";
        program.system = system;
        // Create a collection of parameters associated with the program
        var parameters = new ProgramParameters();

        //[... parameters creation ...]

        // Finally call the program
        try
        {
            program.Call(parameters);
        }
        catch (Exception ex)
        {
            if (system.Errors.Count > 0)
            {
                foreach (Error error in system.Errors)
                {
                    // log somewhere: error.Text
                }
            }
            if (program.Errors.Count > 0)
            {
                foreach (Error error in program.Errors)
                {
                    // log somewhere: error.Text
                }
            }
            // log somewhere: ex.Message
        }
    }
}
finally
{
    system.Disconnect(cwbcoServiceEnum.cwbcoServiceAll);
}

原因分析

cwbx作为ActiveX自动化组件,内部部分对象初始化逻辑依赖Windows消息循环或窗口句柄相关机制。WPF应用本身运行在自带消息循环的UI线程中,组件可以正常高效初始化;而控制台应用默认没有消息循环,导致组件在创建Structure、StructureField等对象时,会触发额外的兼容处理逻辑(比如模拟消息环境),大幅增加参数构建的耗时。

解决方法

1. 为控制台应用添加消息循环

将参数构建逻辑放到带消息循环的线程中执行,模拟WPF的运行环境。示例代码:

using System.Windows.Threading;

// 先完成AS400连接逻辑...

var dispatcher = Dispatcher.CurrentDispatcher;
double buildTime = 0;
// 在Dispatcher线程中执行参数构建
dispatcher.Invoke(() => {
    var watch = System.Diagnostics.Stopwatch.StartNew();
    // 这里放置参数构建与赋值的代码
    //[... parameters creation ...]
    watch.Stop();
    buildTime = watch.Elapsed.TotalSeconds;
});
// 后续继续执行program.Call逻辑

注:需要引用WindowsBase.dll,可通过NuGet安装相关包

2. 预构建参数模板并复用

如果AS400程序的参数结构固定,可在程序启动时提前构建一次参数模板,后续调用仅修改字段值,避免重复创建大量对象:

// 全局或静态变量存储预构建的参数模板
private static ProgramParameters _paramTemplate;

// 程序启动时初始化模板
public static void InitParamTemplate(AS400System system)
{
    var program = new Program();
    program.system = system;
    _paramTemplate = new ProgramParameters();
    // 这里完成所有Structure、StructureField的创建逻辑,构建模板
    //[... parameters creation ...]
}

// 调用时复用模板
var parameters = (ProgramParameters)_paramTemplate.Clone();
// 修改参数字段值
//[... set field values ...]
program.Call(parameters);

3. 替换为原生.NET SDK

放弃cwbx,改用IBM官方提供的IBM.Data.DB2.iSeries库(IBM i Access for .NET),这是原生.NET组件,不依赖ActiveX,性能更稳定,且无需处理消息循环:

using IBM.Data.DB2.iSeries;

// 连接AS400
using (var conn = new iDB2Connection("DataSource=192.168.1.55;UserID=USER;Password=PASSWORD;"))
{
    conn.Open();
    // 调用AS400程序
    using (var cmd = new iDB2Command("CALL BW6IF(?, ?, ?)", conn))
    {
        // 添加复杂结构参数
        var structParam = cmd.Parameters.Add("inputStruct", iDB2Type.Structure);
        structParam.StructureName = "YOUR_STRUCTURE_NAME";
        // 设置结构内字段值
        structParam["FIELD1"].Value = "test";
        structParam["FIELD2"].Value = 123;
        
        // 添加数组参数
        var arrayParam = cmd.Parameters.Add("inputArray", iDB2Type.Array);
        arrayParam.ArrayLength = 300;
        arrayParam.ElementType = iDB2Type.Structure;
        arrayParam.ElementStructureName = "ARRAY_ELEMENT_STRUCT";
        // 循环设置数组元素值
        for(int i=0; i<300; i++)
        {
            arrayParam[i]["ELEMENT_FIELD"].Value = i;
        }
        
        cmd.ExecuteNonQuery();
    }
}

4. 优化参数构建逻辑

批量创建对象时减少频繁COM交互:比如一次性创建所有需要的StructureField,再批量添加到Structure中,避免逐个添加带来的开销。

验证效果

采用消息循环或预构建模板的方案后,控制台应用的参数构建耗时可降至0.5秒以内,与WPF应用性能接近;切换到IBM.Data.DB2.iSeries后,整体性能还能进一步提升。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 21:17:49