ASP.NET C# 外部 SDK 不是线程安全的

ASP.NET C# external SDK not thread-safe

我在 ASP.NET/C#.

有一个网站 API

它使用外部 32 位 ActiveX SDK 与第三方应用程序通信。

根据我的测试,当我们同时连接两个不同的用户时,该 SDK 会出现问题。第二个连接覆盖第一个。

如果我在两个 cURL 循环中调用 API,一个与 userA 连接,另一个与 userB 连接,在某些情况下,对 userA 的调用将得到 userB 的结果。

我的代码中没有任何静态变量,none 肯定会引用 SDK。

我能想到的唯一解决方案是 "lock" 在 API 获取用户响应时。还有其他解决方案吗?如果没有,关于如何在 C# 中执行此操作的任何指示?

API 有多个控制器(想想 customer/invoice/payment/vendor),它们都使用相同的 SDK。因此,对 CustomerController 方法的调用也必须锁定对其他控制器的调用。

锁只需要在我使用 SDK 时处于活动状态(这可能是请求时间的 99%)。

编辑 1:

SDK名为"Interop.AcoSDK.dll",是32位的。 Visual Studio 将文件描述为 "AcoSDK Library"。它是用于会计程序 Acomba 的 SDK。该程序本身的结构非常古老,其起源可追溯到80年代的DOS(当时该程序名为Fortune1000)。与SDK的交互真的不现代

我已经将 DLL 添加到我的项目中,为了使用它,我调用了两个部分。


            AcoSDKX AcoSDK = new AcoSDKX();
            int version = AcoSDK.VaVersionSDK;
            if (AcoSDK.Start(version) != 0)
            {
                throw new Exception("Failed to start SDK");
            }

            cie = new AcombaX();
            if (cie.CompanyExists(config.ciePath) == 0)
            {
                throw new Exception("Company not found");
            }

            int error = cie.OpenCompany(config.appPath, config.ciePath);
            if (error != 0)
            {
                throw new Exception("Failed to open company: " + cie.GetErrorMessage(error));
            }

            AcoSDK.User User = new AcoSDK.User
            {
                PKey_UsNumber = config.user
            };

            try
            {
                error = User.FindKey(1, false);
            }
            catch
            {
                throw new Exception("Failed to find user");
            }

            if (error != 0)
            {
                throw new Exception("Failed to find user");
            }

            error = cie.LogCurrentUser(User.Key_UsCardPos, config.pass);
            if (error != 0)
            {
                throw new Exception("Failed to login in Acomba: " + cie.GetErrorMessage(error));
            }

上面的cie属性是class中的一个private AcombaX cie

我的另一个 class 调用 class 来处理与 SDK 的连接。

我的另一个 class 将其声明为标准对象(非静态)。

上面的 config 指的是具有 company/user 属性的对象, API 请求是针对该对象的。可拨打多家公司。

目前,我的问题是调用不同的公司,数据最终会混淆。因此,来自公司 B 的值将显示在我对公司 A 的查询中,例如,当我同时循环 100 次调用 cURL 中的 API 给两家公司时。对于某些查询,它不会每次都这样做,只是在某些时候这样做。可能是当一个调用打开公司-B 的 SDK 而对公司-A 的调用已经连接到 SDK 但还没有开始请求数据时。

您需要分享更多关于 ActiveX SDK 的信息(实际上没有这样的东西)。 ActiveX一共有三种

(great explanation here)

ActiveX EXE: Unlike a stand-alone EXE file, an ActiveX EXE file is designed to work as an OLE server, which is nothing more than a program designed to share information with another program. It has an .EXE file extension.

ActiveX DLL: ActiveX DLL files are not meant to be used by themselves. Instead, these types of files contain subprograms designed to function as building blocks when creating a stand-alone program. It has a .DLL file extension.

ActiveX Control: Unlike an ActiveX DLL or ActiveX EXE file, an ActiveX Control file usually provides both subprograms and a user interface that you can reuse in other programs. It has an .OCX file extension.

根据 SDK 的格式及其使用方式,可能会有并行调用的解决方案。

用一些代码、示例等更新问题,可能会让我了解更多。

这可能是启动多个应用程序而不是一个应用程序并将它们用作池,从同一个库创建多个对象等等。

我已发表评论要求澄清;我希望您处于可以重新设计此功能的开发阶段。

ASP.NET 通常,对于非平凡的同步进程来说真的很差。很容易耗尽线程池,从 "desktop" 或 RPC 体系结构迁移时,像您描述的并发问题并不少见。

我强烈建议将这些操作的 WebAPI / ASP.NET 架构更改为基于 queue/task 的方法。客户端提交一个任务,然后polls/subscribes得到一个完成结果。这将允许您将后端设计为以任何必要的方式运行,以防止由于共享库导致的数据损坏问题。也许每个公司都有一个处理请求的长期后端进程 - 我对您的需求了解不够,无法提出明智的建议,但您在这里有很多选择。