Исключение при доступе к элементам управления XAML внутри задачи

Если я пытаюсь получить доступ к элементам управления XAML внутри задачи (и task::then), мое приложение Metro XAML всегда останавливается с исключением. Этот же код без проблем работает вне задачи. Я не нашел ответа - что я пропустил?

Отчеты отладчика VS11: Concurrency::unobserved_task_exception

Исключение: приложение вызвало интерфейс, который был маршалирован для другого потока.

Большое спасибо за вашу помощь!

void MyClass::MyMemberFunction()
{
    xamlStoryboard->Stop(); // ok
    xamlImage->Source = ref new BitmapImage(); // ok

    task<void> atask([this] ()
    {
        xamlStoryboard->Stop(); // exception!
        xamlImage->Source = ref new BitmapImage(); //exception!
    });

    atask.then([this] ()
    {
        xamlStoryboard->Stop(); // exception!
        xamlImage->Source = ref new BitmapImage(); //exception!
    });
}

Код продолжения atask.then() выполняется без исключения, если мы добавим task_continuation_context::use_current() в качестве второго параметра:

    atask.then([this] ()
    {
        xamlStoryboard->Stop(); // now ok!
        xamlImage->Source = ref new BitmapImage(); // now ok!
    }, task_continuation_context::use_current());

person Telestes    schedule 10.05.2012    source источник
comment
какое исключение вы получаете?   -  person animaonline    schedule 10.05.2012
comment
Обновлен вопрос - отчеты отладчика VS11: Concurrency :: unobserved_task_exception   -  person Telestes    schedule 10.05.2012
comment
Это мало что говорит, есть ли у него внутреннее исключение?   -  person animaonline    schedule 10.05.2012
comment
Попробуйте вызвать это в потоке Dispatcher, если он есть.   -  person animaonline    schedule 10.05.2012
comment
Исключение: приложение вызвало интерфейс, который был маршалирован для другого потока.   -  person Telestes    schedule 10.05.2012


Ответы (1)


Вы вызываете свои элементы пользовательского интерфейса из потока, отличного от потока пользовательского интерфейса/диспетчера. Вам нужно вызвать методы элементов пользовательского интерфейса с помощью control.Dispatcher.InvokeAsync() или иным образом убедиться, что вы не вызываете их из фонового потока.

person Filip Skakun    schedule 10.05.2012
comment
Спасибо за объяснение. Я нашел: Создание асинхронных операций на C++ для приложений в стиле Metro Глава: Управление потоком выполнения для получения более подробной информации. msdn.microsoft.com/en-us/library /hh750082(v=vs.110).aspx Но дальше я не понимаю, почему я получаю исключения в коде продолжения task::then. Я подумал, что task::тогда код обратного вызова выполняется после завершения задачи и запускается в основном потоке с доступом к элементам управления UI/XAML? - person Telestes; 11.05.2012
comment
Ответ в MSDN: если вы передадите task_continuation_context::use_current() в качестве второго параметра методу «тогда», ваш обратный вызов будет запланирован, как и ожидалось, без необходимости использования диспетчера. Дополнительные сведения см. в разделе Асинхронное программирование на C++ msdn.microsoft.com/ en-us/library/windows/apps/hh780559.aspx примерно на 2/3 пути вниз в разделе «Управление контекстом потока». - person Telestes; 11.05.2012