简体   繁体   English

来自MTA公寓的.NET STA Com对象

[英].NET STA Com Object from MTA apartment

I'm working on a site (MVC) at the moment, which uses ajax quite heavily to request data from slow responding asynchronous resources. 我目前正在开发一个站点(MVC),它使用ajax非常重要地从缓慢响应的异步资源请求数据。

I have a problem though, every request has to first be authorised, and part of that authorisation is to get the current RSA username, by doing Server.CreateObject("Rsacookieapi.RSACookie").GetUserName(). 我有一个问题,每个请求必须首先被授权,并且该授权的一部分是通过执行Server.CreateObject(“Rsacookieapi.RSACookie”)获取当前的RSA用户名.GetUserName()。 The problem is that this particular com object doesn't run on MTApartments, only STAparatments (they don't offer any alternative .net component, so we must use this one), therefore CreateObject fails. 问题是这个特定的com对象不能在MTApartments上运行,只有STAparatments(它们不提供任何替代的.net组件,所以我们必须使用这个),因此CreateObject失败。

I have got round this through much researching by creating a custom route handler that executes the controller context in an STA (equivalent to do ASPCOMPAT=TRUE on webforms), but this brings in a further problem, I can no longer create Asynchronous controller methods when the controller context is being executed from within an STA. 通过创建一个在STA中执行控制器上下文的自定义路由处理程序(相当于在webforms上执行ASPCOMPAT = TRUE),我通过大量研究来解决这个问题,但是这又带来了一个问题,我不能再创建异步控制器方法了。控制器上下文正在STA内执行。

So I started thinking, if I could create the COM object in an STA, and somehow create a delegate/marshall to it, so it could be accessed from MTA, then all would be good. 所以我开始思考,如果我可以在STA中创建COM对象,并以某种方式创建一个委托/ marshall,所以它可以从MTA访问,然后一切都会好。

As a proof of concept, I had a global variable myComObject, which I populated by doing the CreateObject from within an STA request (/StaController/Index). 作为一个概念证明,我有一个全局变量myComObject,我通过在STA请求(/ StaController / Index)中执行CreateObject来填充。

I then tried to access myComObject from an MTA request (/MtaController/Index). 然后我尝试从MTA请求(/ MtaController / Index)访问myComObject。

The great news is, this works. 好消息是,这是有效的。 It appears as if the clr is handling all the marshalling for me. 似乎clr正在为我处理所有的编组。

So I began to write some code, that spawns a new thread in an STA, but the problem is i'm stil required to pass the HttpContext.Current.Server(HttpServerUtilityBase) to the thread, which when I call .CreateObject on just executes it on the MTA of the .Server object anyway. 所以我开始编写一些代码,在STA中生成一个新线程,但问题是我需要将HttpContext.Current.Server(HttpServerUtilityBase)传递给线程,当我调用.CreateObject时才执行它无论如何都在.Server对象的MTA上。

I hope this makes sense? 我希望这是有道理的? To clarify: 澄清:

  1. I don't want any of my controllers or actions to be executed on an STA's 我不希望我的任何控制器或操作在STA上执行
  2. I want to create the object on an STA's and then give access to it from all other MTA's 我想在STA上创建对象,然后从所有其他MTA访问它

I sincerely hope someone has a suggestion! 我衷心希望有人有个建议!

Regards 问候

Karl 卡尔

Option 1: Use Tlbimp to create an assembly. 选项1:使用Tlbimp创建装配。

Have you tried using Tlbimp.exe to create an assembly for the component, and use that? 您是否尝试过使用Tlbimp.exe为组件创建程序集,并使用它? The documentation says this results in "poor performance". 文档说这会导致“性能不佳”。 But this is due to the required marshalling, which is just the same as what you are trying to do here. 但这是由于所需的编组操作,这与您在此处尝试的操作完全相同。

http://msdn.microsoft.com/en-us/library/zwk9h2kb.aspx http://msdn.microsoft.com/en-us/library/zwk9h2kb.aspx

The AspCompat attribute forces the page to execute in STA mode. AspCompat属性强制页面在STA模式下执行。 The runtime throws an exception if the compatibility tag is omitted and an STA component is referenced on the page. 如果省略兼容性标记并且页面上引用了STA组件,则运行时将引发异常。 If you convert the STA component to an assembly using Tlbimp.exe, the runtime does not detect that the component uses the STA model and does not throw an exception, but your application can suffer from poor performance. 如果使用Tlbimp.exe将STA组件转换为程序集,则运行时不会检测到组件使用STA模型并且不会引发异常,但您的应用程序可能会遇到性能不佳的问题。

Option 2: Lie. 选项2:谎言。

It may work fine in your scenario if you just change the registration to "both". 如果您只是将注册更改为“both”,它可能在您的方案中正常工作。 That depends on the object and how you use it. 这取决于对象以及如何使用它。

Provided that you use a fresh object each time, and dispose of the object immediately using Marshall.ReleaseComObject so you aren't tempted to re-use it from another thread, then there will be no issues. 如果您每次都使用一个新对象,并使用Marshall.ReleaseComObject立即处理该对象,这样您就不会想从另一个线程重新使用它,那么就不会有任何问题。

(STA means that the object can only be called from one thread. COM will guarantee that for you, when sharing objects, by marshalling between apartments with different threading models, so you can assume that all objects in your apartment are compatible with your threading model. However you can also provide that guarantee yourself by just not sharing the object and not calling the object from any other threads ). (STA表示只能从一个线程调用该对象。通过在具有不同线程模型的公寓之间进行编组,COM将保证在您共享对象时,您可以假设您公寓中的所有对象都与您的线程模型兼容但是,您也可以通过不共享对象 而不从任何其他线程调用对象来提供自己的保证。

To do this just go into the registry under HKEY_CLASSES_ROOT\\CLSID\\{guid} and change the ThreadingModel key to "Both". 要执行此操作,只需进入HKEY_CLASSES_ROOT\\CLSID\\{guid}下的注册表,并将ThreadingModel键更改为“Both”。

Then stress-test it. 然后进行压力测试吧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM