Копировать разрешения/аутентификацию в дочерние потоки…?

Вот кое-что очень странное, что я заметил.

Я пишу расширение 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;
        });
    }

Кажется почти очевидным, что я упускаю некоторые основы того, как потоки используют разрешения. Поскольку в моем случае предпочтительнее использовать отдельный поток, есть ли способ «скопировать» разрешения/аутентификацию? Может быть, какое-то подражание?

РЕДАКТИРОВАТЬ: В случае, если кто-то еще борется с этим, использование других потоков (или Task, в зависимости от обстоятельств) возможно до тех пор, пока query.BeginExecute(null, null); выполняется в потоке пользовательского интерфейса. Вам нужен способ получить возвращенный IAsyncResultобратно в вызывающий поток, но вы можете сделать это с помощью ManualResetEvent.

Но я все же хотел бы знать, почему проклятые разрешения/аутентификация не распределяются между потоками...

17
задан Shaamaan 18 July 2018 в 18:36
поделиться