Поток Non UI, который выполняется под олицетворенным пользователем, автоматически погружает поток UI? - PullRequest
4 голосов
/ 15 июня 2011

Я искал несколько часов и до сих пор с ним не повезло - поэтому подумал, что я опубликую.

У меня есть приложение WPF, написанное на vb.net, работающее на DotNet 4.0, которое запускаетрабочие потоки для выполнения определенных функций, таких как хеширование файлов и другие трудоемкие процессы.

Некоторые из запущенных потоков должны выдавать себя за другого пользователя, чтобы получить доступ к сетевым ресурсам, к которым вошедший в систему пользователь обычно не может получить прямой доступ (им разрешен контролируемый доступ к сетевым ресурсам через приложение, но не дляпример, через проводник windows).Для этого рабочий поток олицетворяет заранее определенную учетную запись пользователя, которая имеет доступ, который затем позволяет приложению получить доступ к сетевым ресурсам.

Пока этот рабочий поток, работающий под учетной записью олицетворенного пользователя, работает - ему иногда требуетсяобновить локальную компактную базу данных sql 3.5, находящуюся в каталоге Users.Эта база данных доступна только для вошедшего в систему пользователя, а не для олицетворенного пользователя.

Чтобы разрешить это обновление, из олицетворенного рабочего потока у меня есть доступ к объекту UI Dispatcher (он передается при создании потока)в которой я вызываю подпрограмму для обновления базы данных SQL Compact.

Вот интересная проблема, которую я не могу объяснить, но читаю, поскольку кто-то может объяснить это.

Приложение, когда оновызов диспетчера пользовательского интерфейса из рабочего потока приведет к возврату учетных данных вошедших в систему пользователей для обновления базы данных sql в потоке пользовательского интерфейса - и затем, когда вызов UIthread.dispatcher.invoke вернется в рабочий поток - он вернется к олицетворенномуучетная запись рабочего потока.

Сегодня - и у меня нет причины, почему - когда я вызываю поток диспетчера пользовательского интерфейса для обновления базы данных SQL Compact, контекст потока остается у олицетворенного пользователя, а не вошедшего в систему пользователя наПользовательский интерфейс.Это похоже на олицетворенного пользователя, который теперь накладывается на все потоки, включая поток пользовательского интерфейса.

Я пытаюсь понять, каков правильный результат - если UIThread.Dispatcher.Invoke выполнит любой код, вызываемый в соответствии спользовательский контекст потока пользовательского интерфейса (не олицетворенный) ИЛИ вступает ли в силу безупречный пользовательский контекст для обратного вызова invoke в потоке пользовательского интерфейса, потому что он был инициирован из рабочего потока?

Я озадачен, потому что вчера - когдаУ меня была точка останова в подпрограмме UIThread.Dispatcher.Invoked, я мог видеть, что поток выполнялся под учетной записью вошедшего в систему пользователя и обновления базы данных SQL compact работали.Сегодня, однако, тот же код выполняется под олицетворенной учетной записью, и я получаю исключения отказа в доступе при попытке обновить базу данных.

Я проверил ManagedThreadId потока пользовательского интерфейса перед запуском рабочих потоков и могу подтвердитьчто ManagedThreadId при выполнении UIThread.Dispatcher.Invoke возвращается к ManagedThreadId потока пользовательского интерфейса - затем, когда вызов заканчивается и выполнение возвращается в рабочий поток, ManagedThreadId возвращается к правильному рабочему ManagedThreadId.Что не меняется в этот раз, так это Пользователь для этой темы.Похоже, что теперь он остается за имитируемого пользователя все время, пока я не прекратить олицетворение потока.

Может кто-то, пожалуйста, пролить некоторый свет на это - и предложить, если я поступаю по этому поводу все неправильно и должно бытьпытаясь сделать это по-другому.То, что я действительно хочу понять, это то, почему он работал - и почему сейчас он не работает - и нет - никакой код не изменяет этот код между вчера и сегодня.

Извините за длинный пост

Cheers

Удочка.

1 Ответ

3 голосов
/ 15 июня 2011

Возможно, вы захотите взглянуть на контекст выполнения потока.

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

Из CLR через C #, 3d ed pg 721:

В пространстве имен System.Threading есть класс ExecutionContext, который позволяет вамуправлять потоком контекста выполнения потока из одного потока в другой.

...

Если контекст выполнения инициирующего потока не передается вспомогательному потоку, вспомогательный поток будет использовать любой контекст выполненияэто в последний раз связано с этим.Поэтому вспомогательный поток на самом деле не должен выполнять какой-либо код, который зависит от состояния контекста выполнения (например, удостоверение пользователя Windows).

Кроме того, мне пришлось выполнить некоторое олицетворение в ASP.NET.Недавно приложение и Win32 API для LogonUser предложили действительно очень детализированный элемент управления, когда я хотел олицетворять, как я хотел олицетворять (например, сеть, интерактив, сервис и т. д.), а затем быстро возвращаться в один поток.

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

...