如何确保在IIS中使用同一线程执行代码?

时间:2020-03-05 18:47:50  来源:igfitidea点击:

我们在IIS6托管的Web服务中使用了第三方dll。问题在于,一旦将此dll加载到内存中,如果一个线程与创建它的线程不同,则尝试抛出该异常,否则将抛出AccessViolationException异常。工作进程是多线程的,每次对Web服务的调用都会从池中获得一个随机线程。我们试图从内存中卸载它,并在每次需要它时都重新加载它,但是我猜只有前端是.Net,其余部分是不受管理的,因此它实际上从未真正从内存中完全卸载。我们正在使用VB和.Net 2.0。有什么建议?

(回应罗伯·沃克)

我们考虑过创建一个新线程并使用它来调用dll,但是如何使线程坐下来并等待调用呢?如何在没有.Net 3.0提供的Dispatcher类的情况下将调用委派给线程?创建隐藏的表单并将其置于消息循环中可能会起作用。然后我们可以调用表单的Invoke()方法。但是,如果我们在IIS托管的Web服务中创建表单,就会看到很多问题。

解决方案

回答

我已经阅读了有关.net 3.0中称为Dispatcher的类,该类允许我们将线程放入循环中,然后使用委托调用方法Invoke()来执行使用线程的方法。但是,如果我们无法更新到.Net 3.0,则此解决方案将不起作用。另一个解决方案是将第三方dll托管在服务器上的另一个应用程序中,并使用某种形式的Remoting对其进行访问。但是我们可能仍然对Remoting有问题,因为它的行为类似于IIS,并且还会选择一个随机线程来执行代码。为了解决这个问题,我们可以在dll周围放置一个包装器,并使用窗体的Invoke()方法将其用于将调用委派给UI线程。

回答

我认为我们需要考虑使用一个包装线程来处理对DLL的所有调用,并处理序列化。

该线程在托管线程池之外,因此我们可以控制其生存期。但是,除非我们可以阻止IIS重新启动Web服务所在的应用程序域,否则即使这也并非万无一失。

我们还需要担心当同时出现两个Web服务请求时会发生什么情况。是对DLL的每个调用都是独立的,还是必须在将任何其他请求提供服务之前将与单个Web服务请求关联的所有调用组合在一起?

回答

我们可以创建一个承载额外DLL的服务。通过远程访问服务,这将调度调用管理DLL的线程。

这样,我们可以控制调用DLL的线程以及线程的生存期。

回答

我有点生锈,但是我们可以尝试将对DLL的调用包装在单个线程的单元COM对象中。这样可以确保所有调用都通过COM对象的Windows消息传递线程。我认为我们必须在组件服务中的服务器应用程序中注册组件才能执行此操作。

回答

我们可以在不同的线程中将dll作为不同的实例运行吗?就像thread1创建该第三方dll的实例一样,thread2也这样做,但是只要thread1不尝试使用thread2的实例,它就不会抛出该异常?如果真是这样,.Net永远不会在加载代码后卸载任何代码,如果加载程序集然后将其删除,则它仍位于该应用程序池中。如果一次可以创建多个实例,则可以将其加载到根据请求控制的单独的应用程序池中,然后卸载该应用程序池。性能可能会下降。