这是我注意到的非常奇怪的事情。
我正在编写一个 CRM 2011 Silverlight 扩展,而且,在我的本地开发实例上一切都很好。应用程序使用 OData 进行通信,并System.Threading.Tasks.Task
在后台执行所有操作(FromAsync
是一种祝福)。
然而,我决定在 CRM 2011 Online 中测试我的应用程序,令我惊讶的是,它不再工作了。结束检索任务时,我会收到安全异常。
使用 Fiddler,我发现 CRM 试图将我重定向到实时登录页面,考虑到我已经登录,这没有多大意义。
经过更多尝试,我发现错误是因为我从与 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;
});
}
似乎很明显,我缺少一些关于线程如何使用权限的基础知识。由于在我的情况下最好使用单独的线程,有没有办法“复制”权限/身份验证?也许是某种模仿?
Task
编辑:如果其他人为此苦苦挣扎,只要query.BeginExecute(null, null);
在 UI 线程上执行,就可以使用其他线程(或视情况而定)。您需要一种方法来检索返回IAsyncResult
给调用线程,但您可以使用ManualResetEvent
.
但我仍然想知道为什么线程之间不共享该死的权限/身份验证......