在使用Task.Run()在其他线程中运行某些代码的ASP.NetWebForms应用程序中使用DryIOC时出现问题。我们在ASP.NET WebForms应用程序中遇到了无法同时使用HttpContextScopeContext和ThreadScopeContext的问题。我们测试了每个重用范围,它没有同时工作。我们有一些Http处理程序,在它们的代码中,这些处理程序不工作,我们注入的服务没有得到解决。测试项目的链接是Here。问题是,我们如何使用DryIOC,以便我们可以同时拥有Scoped服务和Thread服务(在Task.Run()中解决)。
我们遇到错误消息:DryIoc.ContainerException:'code:Error.NoCurrentScope;消息:当前作用域不可用-可能您正在注册到作用域之外或从作用域之外解析。这也可能是因为作用域依赖项在其父链中具有单例,因此依赖项从根容器解析器解析。当前解析程序上下文为:container with ambient DryIoc.ThreadScopeContext without scope with Rules without {ThrowOnRegisteringDisposableTransient}.'
谢谢你的帮助。
最好的问候。
我们开发了一个示例WebForms应用程序,并测试了我们所知道的东西,但它不起作用。我们希望在我们的Web页面中既有Scoped生存期,也能在Task.Run()代码中解析我们的服务。
1条答案
按热度按时间6xfqseft1#
我在这里唯一的建议是,你必须知道网页是如何工作的,以及所谓的Web服务器的工作生命周期。
记住,Web开发=状态更少!
这意味着在代码隐藏运行后,页面被发送回客户端,在服务器上,该网页,代码隐藏和HTTP上下文现在被销毁,被释放,并超出范围。页面类、代码、变量和HTTP上下文现在都消失了!
当用户点击网页上的按钮时,网页被发送到服务器。这就是所谓的往返旅程的开始。页面类的一个新示例被创建,该页面类中的所有变量现在从头开始(它们在页面被发送到服务器的示教时间开始)。
此时,您的代码将运行,并且可以修改服务器上该网页的DOM。代码完成后,页面将被发送回客户端。在服务器侧,如所述的页面类被处置,从存储器中移除。Web服务器现在正在等待任何用户单击按钮并回发。然而,服务器对客户端浏览器正在做什么一无所知。用户可以关闭计算机。他们可以使用浏览器开始在Amazon.com上购物。你的服务器不知道这个事实,也没有持久的HTTP上下文或任何发生在服务器端的事情。
因此,页面生命周期(往返)看起来像这样:
x1c 0d1x的数据
请注意,您的页面类代码并不在服务器的内存中.
你没有这个:
的
因此,Web服务器只是在等待任何用户回发网页。每个用户在内存中没有他们的页面、代码或变量的副本。这里每个用户都没有现有的http上下文。您有一个http上下文,并且在服务器处理页面的过程中只有一个。
所以,用户点击一个按钮,页面生命周期就开始了。
这一点:
的
我们的网页被发送到服务器。然后http上下文现在存在,并且只会存在很短的时间。
的
现在,页面类的示例已经创建,您的代码开始运行。
您的代码可以修改控件(甚至控件可见或不可见),但页面不与用户交互-只有代码可以修改网页(用户看不到一个更改或许多更改)。
所以,一个变化,或许多变化的网页可能会发生,但当你更新的东西,如文本框等,用户还没有看到这些变化。所以,如果你运行一个循环1到10,并更新一个文本框,文本框将被更新1到10。然而,最终用户什么也看不到,因为该网页(和代码)正在服务器上运行。
服务器上的网页正在发生更改-客户端浏览器不再拥有该网页!当您的服务器代码运行时,并更新浏览器中的DOM?最终用户只看到“旋转器”,浏览器正在等待。最终用户此时看不到对浏览器所做的任何更改。
一旦你的所有代码都运行完了,那么,也只有在那时,页面才会返回到客户端浏览器。
服务器端的类示例和代码(以及变量)都是TOSSED OUT - DOES NOT exist!您的服务器端页面类已被处置-从内存中删除,并且后面的网页代码不再存在于内存中,也不存在于任何上下文中。
因此,页面返回到客户端,重新显示,加载JavaScript,然后JavaScript开始运行。因此,即使是客户端页面现在100%重新加载。
x1c4d 1x型
那么,现在有了上面的知识武装了一个帖子的回帖和轮转类型(即页面生命周期)?
因此,从代码背后,您可以启动整个新的单独线程,并使该代码100%独立于网页运行。然而,没有现有的HTTP上下文,一旦页面被发送回客户端,页面背后的代码就不再存在。Web服务器正在等待处理来自任何用户的任何网页。每个用户都不存在代码隐藏。这里有一个服务器和一个http上下文。
所以,当你可以自由地启动一个新的进程线程,独立于那个网页的代码和页面类吗?网页的代码、该网页的HTTP上下文以及该网页类中的变量?它们的寿命很短,并且只在页面在服务器上运行的短时间内存在。如前所述,页面返回客户端的瞬间也是所有代码、它们的变量和HTTP上下文现在都超出范围的时刻。Web服务器现在正在等待接收和处理来自任何用户的任何传入页面。当这种情况发生时,只有当http上下文存在时。
所以,在网络世界中,你没有每个用户的“内存”或“变量”。您有一个Web服务器,并在其后面运行一组代码。一旦一个请求的页面处理完成并且页面生命周期完成?然后将该用户的上下文和代码抛出内存,并释放类和变量。而且这包括这里的http上下文(它也不见了!!!).
因此,您可以开始一个新的任务/任务。然而,这样的线程和任务将不具有任何一个用户的任何知识。它必须是一个100%独立的代码库,并且没有UI或与特定用户没有交互。并且这样的代码没有任何http上下文。
现在,掌握了上述知识吗?
显然,你不能将HTTP上下文传递给一个单独的新进程线程,因为用户代码、网页和后面的页面类代码在后面的代码完成并将页面发送回客户端的瞬间都超出了作用域。
当然,这意味着您启动的这些工作进程或单独的线程不能使用也不能拥有HTTP上下文,因为HTTP上下文很快就会超出范围并且非常短暂。
如果您需要进程代码或服务器代码来向每个Web用户(或所有用户)推送通知,那么您可以引入Web Socket,并保持并强制从Web服务器到客户端浏览器的实时连接。
当然,设置一个自定义的Web Socket可能是一个繁重的工作。因此,大多数人倾向于采用现有的框架,其中从服务器到客户端的Web Socket字的所有代码和部分都是为您编写的。
基于此概念允许客户端浏览器实时更新的通用框架称为SignalR,您可以在此处阅读此概念:
https://learn.microsoft.com/en-us/aspnet/signalr/overview/getting-started/introduction-to-signalr
因此,上述内容保持了一个对浏览器开放的实时网络(Web Socket)连接,因此您可以构建真实的浏览器更新系统,在其中您不必担心HTTP上下文超出范围。因此,使用SignalR允许您构建并运行服务器端代码,并将信息或通知推送到客户端浏览器,并且在没有现有HTTP上下文的情况下这样做,正如我所指出的,它会很快超出范围,并且非常短暂。
上面解释了你的错误。这个错误是你的http上下文很快就超出了范围,而且寿命很短。换句话说,你可以自由地创建一个新的单独的任务,但是由于网页的无状态特性,这些任务不能也不会有任何可用的http上下文。当然,您可以让一个网页“查询”您启动的单独任务线程的状态。您可以通过更新数据库中的值来实现这一点,然后让网页在其短暂的服务器端生命周期内查询这些数据库值。或者,您可以让单独的任务更新session()中的值,其后面的网页代码可以再次查询。
或者,如建议的那样,您可以设置并创建一个Web Socket,然后允许客户端浏览器保持与服务器的网络连接(因此考虑SignalR)。