我们的业务层服务器上有一个 Web 前端。
我们的 Web 应用程序中的某些页面会实例化非常长时间运行的任务(可能长达 10 多分钟)。处理这些请求的方式是这样的: -
(在 HTTP 请求线程上)
- 我们连接到业务服务器。
- 我们创建一个新线程来进行长时间运行的调用,并传入连接对象。
- 然后 HTTP 请求完成,将句柄传回浏览器,
- 浏览器会定期轮询 Web 服务器以获取有关长时间运行的任务进度的更新。
对业务服务器的所有请求都经过身份验证 - 连接的用户主体页面必须有权调用业务服务器上的方法。
只要我们的 Web 应用程序在经典模式下运行,这种机制就可以正常工作。当我们在管道模式下运行时,我们会在浏览器轮询时得到 ObjectDisposedExceptions。
System.ObjectDisposedException: Safe handle has been closed
at System.StubHelpers.StubHelpers.SafeHandleC2NHelper(Object pThis, IntPtr CleanupWorkList)
at Microsoft.Win32.Win32Native.GetTokenInformation(SafeTokenHandle TokenHandle, UInt32 TokenInformationClass, SafeLocalAllocHandle TokenInformation, UInt32 TokenInformationLength, ref UInt32 ReturnLength)
at System.Security.Principal.WindowsIdentity.GetTokenInformation(SafeTokenHandle tokenHandle, TokenInformationClass tokenInformationClass, ref UInt32 dwLength)
at System.Security.Principal.WindowsIdentity.get_User()
at System.Security.Principal.WindowsIdentity.GetName()
at System.Security.Principal.WindowsIdentity.get_Name()
问题似乎是用于建立连接的 windows 主体在原始请求结束时被释放(这是可以理解的 - 事实上我很惊讶代码完全可以工作!)。
作为解决此问题的一种方法,我想知道是否可以创建 HTTP 请求主体的副本并使用它来创建连接(并在长时间运行的任务完成时将其丢弃),或者是否可以模拟主体处理后,工作线程上的HTTP请求原理?
更新
(我在 Aliostad 的问题下的评论是不正确的:测试页面确实失败了。我设法让自己感到困惑,以至于我编写了我的测试页面,因此它没有使用与真实(错误)代码相同的代码路径。没关系!)
我已经为这个问题编写了一个“解决方法”: - 我很幸运地知道在调用业务服务器之前业务服务器逻辑将查询哪些角色/组。因此,我的解决方法是根据请求的主体在这些角色中的成员身份创建一个新的通用主体。长时间运行的任务使用通用主体运行。
我对这种解决方法不是 100% 满意,因为它在很大程度上是一种“黑客行为”——即我可以看到,如果某些逻辑(非常明智)检查验证主体的身份是否经过身份验证,它很容易崩溃。
因此,我仍然非常感谢对此问题的任何帮助/见解。
谢谢