locked
При доступе к свойствам элемента происходит исключение UnauthorizedAccessException RRS feed

  • Вопрос

  • Создаю элементы, помещаю их на странице приложения и в массив. При этом я асинхронно скачиваю html страницы с помощью WebClient (после того, как произошло событие Loaded страницы приложения). Подписываюсь на скачивание каждой страницы событием HtmlDownloaded. Чтобы каждая обработка события происходила асинхронно, в HtmlDownloaded пишу следующее:

    private void HtmlDownloaded(object sender, DownloadStringCompletedEventArgs e)
    {
        Task task = new Task(() => Func(e));
        task.Start();
    }
    private void Func(DownloadStringCompletedEventArgs e)
    {
       // Здесь обрабатываю скачивание html
    }

    Если в Func я обращаюсь к любому свойству какого - либо элемента из массива, созданного в начале, у меня возникает исключение UnauthorizedAccessException. Не могу понять в чем проблема. Заранее спасибо!

    17 ноября 2013 г. 13:02

Ответы

  • Это связано с тем, что вы обращаетесь к элементам не из того потока!
    Обратитесь к ним из нужного потока, например, из SyncContext (UIThread)
    17 ноября 2013 г. 15:23
  • Никита все верно сказал про вызов не из UI потока. Но я внесу поправки:

    1. Не SyncContext, а SynchronizationContext.

    2. SynchronizationContext обычно кастомизируют, т.к. в рабочем потоке он возвращает null, поэтому просто создают класс-контейнер, который в UI потоке инициализируют текущим SynchronizationContext.Current. Т.е. теперь в рабочем потоке можно обращаться к своему классу-контейнеру, а не к SynchronizationContext.

    3. Можете использовать Dispatcher.BeginInvoke

    Dispatcher.BeginInvoke(() =>
                {
                    //какой-то код, требующий синхронизации потоков.
                });


    17 ноября 2013 г. 21:57
  • Можете использовать Dispatcher.BeginInvoke


    Это же уже устарело. Используйте Async/Await.

    Windows.UI.Core.CoreWindow.GetForCurrentThread() в рабочем потоке не вытащишь, все равно придется его инстанс вытаскивать в UI потоке и вставлять в контейнер что бы использовать в рабочем потоке. 

    Выше Dispatcher(вариант №3) подтягивается у текущей страницы(PhoneApplicationPage) и работает в рабочем потоке, хотя в MVVM это не сработает, т.к. страницы ж там нет. Так что лучше всего создать класс контейнер и хранить механизм синхронизации потоков в нем и использовать где необходимо.

    18 ноября 2013 г. 10:37

Все ответы

  • Это связано с тем, что вы обращаетесь к элементам не из того потока!
    Обратитесь к ним из нужного потока, например, из SyncContext (UIThread)
    17 ноября 2013 г. 15:23
  • Никита все верно сказал про вызов не из UI потока. Но я внесу поправки:

    1. Не SyncContext, а SynchronizationContext.

    2. SynchronizationContext обычно кастомизируют, т.к. в рабочем потоке он возвращает null, поэтому просто создают класс-контейнер, который в UI потоке инициализируют текущим SynchronizationContext.Current. Т.е. теперь в рабочем потоке можно обращаться к своему классу-контейнеру, а не к SynchronizationContext.

    3. Можете использовать Dispatcher.BeginInvoke

    Dispatcher.BeginInvoke(() =>
                {
                    //какой-то код, требующий синхронизации потоков.
                });


    17 ноября 2013 г. 21:57
  • Можете использовать Dispatcher.BeginInvoke


    Это же уже устарело. Используйте Async/Await.
    18 ноября 2013 г. 9:36
  • Можете использовать Dispatcher.BeginInvoke


    Это же уже устарело. Используйте Async/Await.

    Windows.UI.Core.CoreWindow.GetForCurrentThread() в рабочем потоке не вытащишь, все равно придется его инстанс вытаскивать в UI потоке и вставлять в контейнер что бы использовать в рабочем потоке. 

    Выше Dispatcher(вариант №3) подтягивается у текущей страницы(PhoneApplicationPage) и работает в рабочем потоке, хотя в MVVM это не сработает, т.к. страницы ж там нет. Так что лучше всего создать класс контейнер и хранить механизм синхронизации потоков в нем и использовать где необходимо.

    18 ноября 2013 г. 10:37