在模拟用户下运行的非UI线程是否会自动进入UI线程?

时间:2011-06-15 04:06:09

标签: vb.net multithreading impersonation dispatcher

我一直在寻找几个小时,到目前为止还没有运气 - 所以我想发帖。

我在vNet.net上编写了一个在DotNet 4.0上运行的WPF应用程序,该应用程序启动工作线程以执行特定功能,例如散列文件和其他处理器/时间密集型例程。

启动的某些线程需要冒充不同的用户才能访问登录用户通常无法直接访问的网络资源(允许他们通过应用程序对网络资源进行受控访问,但不允许Windows资源管理器)。为此,工作线程模拟一个预先确定的用户帐户,该帐户具有访问权限,然后允许应用程序访问网络资源。

虽然在模拟的用户帐户下运行的这个工作线程正在运行 - 它偶尔需要更新位于Users目录中的本地sql 3.5压缩数据库。此数据库只能由登录用户访问 - 而不是模拟用户。

要允许此更新,我可以从模拟的工作线程访问UI Dispatcher对象(在创建线程时传递它),在该对象中,我调用子例程来更新SQL压缩数据库。

这是一个有趣的问题,我无法解释,但请继续阅读,因为有人可以解释这一点。

应用程序从工作线程调用UI Dispatcher时将退回到已登录的用户凭据以更新UI线程中的sql数据库 - 然后当UIthread.dispatcher.invoke调用返回到工作线程时 - 它会回到模拟的工作线程帐户。

今天 - 我没有理由 - 当我调用UI调度程序线程来更新SQL Compact数据库时,线程上下文仍然存在于模拟用户 - 而不是UI线程上的登录用户。就像模仿用户现在强加于所有线程 - 包括UI线程。

我想要了解的是什么是正确的结果 - 如果UIThread.Dispatcher.Invoke执行在UI线程的用户上下文(未模拟)下调用的任何代码,或者被模仿的用户上下文是否生效在UI线程上调用回调,因为它是从工作线程启动的?

我很困惑,因为昨天 - 当我在UIThread.Dispatcher.Invoked例程中有一个断点时,我可以看到线程在登录用户帐户下执行,并且SQL压缩数据库的更新有效。然而,今天,相同的代码在模拟帐户下执行,并且在尝试更新数据库时我获得访问被拒绝的异常。

我在启动工作线程之前检查了UI线程的ManagedThreadId,并且能够确认执行UIThread.Dispatcher.Invoke时的ManagedThreadId返回到UI线程的ManagedThreadId - 然后当调用结束并执行返回时对于工作线程,ManagedThreadId返回到正确的工作者ManagedThreadId。这一次没有改变的是该线程的用户。它似乎现在仍然留在模拟用户身上,除非我明确地结束了模拟的模仿。

有人可以对此有所了解 - 并建议我是否认为这一切都是错误的,应该尝试以另一种方式做到这一点。我真正想了解的是为什么它一直在工作 - 为什么现在它没有 - 并且没有 - 在昨天和今天之间没有代码更改此代码。

对不起,很长的帖子

干杯

杆。

1 个答案:

答案 0 :(得分:3)

您可能想查看线程的执行上下文。

http://msdn.microsoft.com/en-us/library/system.threading.executioncontext.aspx

从CLR到C#,3d ed pg 721:

  

在System.Threading命名空间中,有一个ExecutionContext类,允许您控制线程的执行上下文如何从一个线程流向另一个线程。

     

...

     

如果启动线程的执行上下文没有流向辅助线程,则辅助线程将使用它最后与之关联的执行上下文。因此,辅助线程实际上不应该执行任何依赖于执行上下文状态的代码(例如用户的Windows标识)。

另外,最近我不得不在ASP.NET应用程序中进行一些模拟,当我想模仿时,LogonUser win32 api提供了一些非常细粒度的控制,我想如何冒充(即网络,交互,服务,等),然后在单个线程中快速恢复。

http://msdn.microsoft.com/en-us/library/ff647404.aspx#paght000023_impersonatingusinglogonuser