Здесь что-то очень странное, что я заметил.
Я пишу CRM 2011 Silverlight расширения, и, ну, все в порядке на моем локальном экземпляре разработки. Приложение использует OData для связи и много использует System.Threading.Tasks.Task
для выполнения всех операций в фоновом режиме (FromAsync
является благословением).
Однако я решил проверить свое приложение в CRM 2011 Online и, к моему удивлению, нашел, что он больше не будет работать; Я получаю исключение безопасности при завершении поиска задач.
Используя Fiddler, я обнаружил, что CRM пытается перенаправить меня на страницу входа в систему Live, что не имеет большого смысла, учитывая, что я уже вошел в систему.
После нескольких попыток я обнаружил, что ошибки были связаны с тем, что я обращался к службе из другого потока, чем поток пользовательского интерфейса.
Вот пример:
//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;
});
}
Кажется почти очевидным, что у меня отсутствуют некоторые основы того, как потоки используют разрешения. Так как использование отдельного потока предпочтительнее в моем случае, есть ли способ "скопировать" разрешения/аутентификацию? Возможно, какая-то олицетворение?
EDIT: если кто-то еще борется с этим, возможно использование других потоков (или Task
, если это возможно), если в потоке пользовательского интерфейса выполняется query.BeginExecute(null, null);
. Вам нужен способ вернуть возвращенный IAsyncResult
обратно в вызывающий поток, но вы можете сделать это с помощью ManualResetEvent
.
Но я все равно хотел бы знать, почему чернильные разрешения/аутентификация не разделяются между потоками...