gpt4 book ai didi

c# - 将权限/身份验证复制到子线程...?

转载 作者:可可西里 更新时间:2023-11-01 03:02:23 24 4
gpt4 key购买 nike

这是我注意到的一些非常奇怪的事情。

我正在编写 CRM 2011 Silverlight 扩展,在我的本地开发实例上一切正常。该应用程序使用 OData 进行通信,并大量使用 System.Threading.Tasks.Task 来执行后台的所有操作(FromAsync 是一种祝福)。

但是,我决定在 CRM 2011 Online 中测试我的应用程序,令我惊讶的是,它不再有效;结束检索任务时我会收到安全异常。

使用 Fiddler,我发现 CRM 试图将我重定向到 Live 登录页面,考虑到我已经登录,这没有多大意义。

经过更多尝试,我发现错误是因为我从与 UI 线程不同的线程访问服务。

这是一个简单的例子:

    //this will work
private void button1_Click(object sender, RoutedEventArgs e)
{
var query = ctx.AccountSet;
query.BeginExecute((result) =>
{
textBox1.Text = query.EndExecute(result).First().Name;
}, null);
}

//this will fail
private void button2_Click(object sender, RoutedEventArgs e)
{
System.Threading.Tasks.Task.Factory.StartNew(RestAsync);
}

void RestAsync()
{
var query = ctx.AccountSet;
var async = query.BeginExecute(null, null);
var task = System.Threading.Tasks.Task.Factory.FromAsync<Account>(async, (result) =>
{
return query.EndExecute(result).First(); // <- Exception thrown here
});
textBox1.Dispatcher.BeginInvoke(() =>
{
textBox1.Text = task.Result.Name;
});
}

很明显,我缺少有关线程如何使用权限的一些基础知识。由于在我的情况下使用单独的线程更可取,有没有办法“复制”权限/身份验证?也许是某种模仿?

编辑:如果其他人正在为此苦苦挣扎,只要 query.BeginExecute(null, null) 就可以使用其他线程(或 Task,视情况而定) ; 在 UI 线程上执行。您需要一种方法将返回的 IAsyncResult 检索回调用线程,但您可以使用 ManualResetEvent 来实现。

但我仍然想知道为什么线程之间不共享该死的权限/身份验证...

最佳答案

我不太确定,这是否有帮助。但是我找到了 Jeffrey Richter 第 770 页的描述

“与控制台应用程序一样,ASP.NET Web 窗体和 XML Web 服务应用程序允许任何线程做任何它想做的事。当线程池线程开始处理客户端的请求,它可以假设客户的文化(System.Globalization.CultureInfo),允许Web 服务器返回数字、日期和时间的特定于文化的格式。5 在此外,Web 服务器可以采用客户端的身份(System.Security.Principal。IPrincipal) 以便服务器只能访问允许客户端访问的资源使用权。当线程池线程产生异步操作时,它将完成由另一个线程池线程执行,该线程将处理异步操作的结果。虽然这项工作是代表原始客户要求执行的,但文化默认情况下,身份信息不会流向新的线程池线程,因此任何代表客户完成的额外工作现在没有使用客户的文化和身份信息。理想情况下,我们希望文化和身份信息流向另一个线程池线程仍在代表同一个客户端工作。”

这是他的例子,我希望这会有所帮助。

private static AsyncCallback SyncContextCallback(AsyncCallback callback) 
{
SynchronizationContext sc = SynchronizationContext.Current;
// If there is no SC, just return what was passed in
if (sc == null) return callback;
// Return a delegate that, when invoked, posts to the captured SC a method that
// calls the original AsyncCallback passing it the IAsyncResult argument
return asyncResult => sc.Post(result => callback((IAsyncResult)result), asyncResult);
}

protected override void OnMouseClick(MouseEventArgs e) {
// The GUI thread initiates the asynchronous Web request
Text = "Web request initiated";
var webRequest = WebRequest.Create("http://Wintellect.com/");
webRequest.BeginGetResponse(SyncContextCallback(ProcessWebResponse), webRequest);
base.OnMouseClick(e);
}

private void ProcessWebResponse(IAsyncResult result) {
// If we get here, this must be the GUI thread, it's OK to update the UI
var webRequest = (WebRequest)result.AsyncState;
using (var webResponse = webRequest.EndGetResponse(result)) {
Text = "Content length: " + webResponse.ContentLength;
}
}

这是我在我的应用程序中使用的内容

 public override void UpdateCanvas(object parameter)
{
Action<GraphPane> startToUpdate = StartToUpdate;
GraphPane selectedPane = Canvas.HostingPane.PaneList.Find(p => p.Title.Text.Equals(defaultPanTitle));
startToUpdate.BeginInvoke(selectedPane, FormSyncContext.SyncContextCallback(RefreshCanvas), selectedPane);
}

public static AsyncCallback SyncContextCallback(AsyncCallback callback)
{
// Capture the calling thread's SynchronizationContext-derived object
SynchronizationContext sc = SynchronizationContext.Current;

// If there is no SC, just return what was passed in
if (sc == null) return callback;

// Return a delegate that, when invoked, posts to the captured SC a method that
// calls the original AsyncCallback passing it the IAsyncResult argument
return asyncResult => sc.Post(result => callback((IAsyncResult)result), asyncResult);
}

关于c# - 将权限/身份验证复制到子线程...?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10513215/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com