【发布时间】:2020-08-15 05:50:31
【问题描述】:
我们有一个旧的第 3 方系统(我们称之为 Junksoft® 95),我们通过 PowerShell 进行交互(它公开了一个 COM 对象),我正在将它包装在一个 REST API(ASP.NET 框架4.8 和 WebAPI 2)。我使用System.Management.Automation nuget 包创建了一个PowerShell,在其中我将Junksoft 的COM API 实例化为dynamic 对象,然后我使用它:
//I'm omitting some exception handling and maintenance code for brevity
powerShell = System.Management.Automation.PowerShell.Create();
powerShell.AddScript("Add-Type -Path C:\Path\To\Junksoft\Scripting.dll");
powerShell.AddScript("New-Object Com.Junksoft.Scripting.ScriptingObject");
dynamic junksoftAPI = powerShell.Invoke()[0];
//Now we issue commands to junksoftAPI like this:
junksoftAPI.Login(user,pass);
int age = junksoftAPI.GetAgeByCustomerId(custId);
List<string> names = junksoftAPI.GetNames();
当我在同一个线程上运行所有这些时(例如,在控制台应用程序中),这工作正常。但是,由于某种原因,当我将junksoftAPI 放入System.Web.Caching.Cache 并从我的网络应用程序中的不同控制器中使用它时,这通常不起作用。我说 ususally 因为当 ASP.NET 碰巧将传入调用传递给创建 junksoftAPI 的线程时,这实际上是有效的。如果没有,Junksoft 95 会给我一个错误。
我有什么办法可以确保与junksoftAPI 的所有交互都发生在同一个线程上?
注意,我不想将整个 Web 应用程序变成单线程应用程序!控制器和其他地方的逻辑应该在不同的线程上正常发生。应该只是 Junksoft 特定线程上发生的 Junksoft 交互,如下所示:
[HttpGet]
public IHttpActionResult GetAge(...)
{
//finding customer ID in database...
...
int custAge = await Task.Run(() => {
//this should happen on the Junksoft-specific thread and not the next available thread
var cache = new System.Web.Caching.Cache();
var junksoftAPI = cache.Get(...); //This has previously been added to cache on the Junksoft-specific thread
return junksoftAPI.GetAgeByCustomerId(custId);
});
//prepare a response using custAge...
}
【问题讨论】:
-
这种行为听起来很像我们为 GUI 类强制执行的规则。也许他们的解决方案也有效? stackoverflow.com/a/14703806/3346583
-
对于 COM,您可能需要抽水。因此,您需要一个单独的 STA 线程来创建它并编组对其的所有调用。
-
你说的是junksoft,但这对于System.Printing.PrintQueue之类的东西也很有用
标签: c# asp.net multithreading powershell asp.net-web-api2