C# 将权限/身份验证复制到子线程。。。?

C# 将权限/身份验证复制到子线程。。。?,c#,multithreading,task-parallel-library,dynamics-crm-2011,silverlight-5.0,C#,Multithreading,Task Parallel Library,Dynamics Crm 2011,Silverlight 5.0,我注意到了一件非常奇怪的事 我正在编写一个CRM 2011 Silverlight扩展,在我的本地开发实例上一切都很好。应用程序使用OData进行通信,并大量使用System.Threading.Tasks.Task在后台执行所有操作(fromsync是件好事) 然而,我决定在CRM 2011 Online中测试我的应用程序,令我惊讶的是,它不再工作了;在结束检索任务时,我将收到一个安全异常 使用Fiddler,我发现CRM试图将我重定向到Live登录页面,考虑到我已经登录,这没有多大意义 在多

我注意到了一件非常奇怪的事

我正在编写一个CRM 2011 Silverlight扩展,在我的本地开发实例上一切都很好。应用程序使用OData进行通信,并大量使用
System.Threading.Tasks.Task
在后台执行所有操作(
fromsync
是件好事)

然而,我决定在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;
        });
    }
//这样就行了
私有无效按钮1\u单击(对象发送者,路由目标)
{
var query=ctx.AccountSet;
query.BeginExecute((结果)=>
{
textBox1.Text=query.EndExecute(result.First().Name;
},空);
}
//这将失败
私有无效按钮2\u单击(对象发送者,路由目标)
{
System.Threading.Tasks.Task.Factory.StartNew(重新同步);
}
void RestAsync()
{
var query=ctx.AccountSet;
var async=query.BeginExecute(null,null);
var task=System.Threading.Tasks.task.Factory.fromsync(异步,(结果)=>
{
返回query.EndExecute(result).First();//
{
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);
 }
public override void UpdateCanvas(对象参数)
{
操作startToUpdate=startToUpdate;
GraphPane selectedPane=Canvas.HostingPane.PaneList.Find(p=>p.Title.Text.Equals(defaultPanTitle));
StartUpdate.BeginInvoke(selectedPane,FormSyncContext.SyncContextCallback(RefreshCanvas),selectedPane);
}
公共静态异步回调SyncContextCallback(异步回调回调)
{
//捕获调用线程的SynchronizationContext派生对象
SynchronizationContext sc=SynchronizationContext.Current;
//如果没有SC,只需返回传入的内容
如果(sc==null)返回回调;
//返回一个委托,该委托在调用时向捕获的SC发布一个
//调用原始AsyncCallback并将IAsyncResult参数传递给它
返回asyncResult=>sc.Post(结果=>callback((IAsyncResult)结果),asyncResult);
}

这可能与。很有可能,但我想指出,在本地、内部CRM服务器上测试我的代码时,一切正常。因此,到底发生了什么还不清楚。