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一共有三种
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得到一个完成结果。这将允许您将后端设计为以任何必要的方式运行,以防止由于共享库导致的数据损坏问题。也许每个公司都有一个处理请求的长期后端进程 - 我对您的需求了解不够,无法提出明智的建议,但您在这里有很多选择。
我在 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一共有三种
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得到一个完成结果。这将允许您将后端设计为以任何必要的方式运行,以防止由于共享库导致的数据损坏问题。也许每个公司都有一个处理请求的长期后端进程 - 我对您的需求了解不够,无法提出明智的建议,但您在这里有很多选择。