Новичок: недопустимый межпоточный доступ с использованием GetAsync - PullRequest
0 голосов
/ 06 июля 2011

Я ценю, что GetAsync, ну, в общем, асинхронный, но я не могу найти никакой документации о том, как его использовать.На этом этапе все, что я хочу, это получить свое имя и присвоить его текстовому блоку.Конечно, если я сделаю это в блоке _fbClient.GetCompleted + = / _fbClient.GetAsync ("/ me"), он получит ошибку исключения недопустимого доступа к многопоточному потоку.

В коде ниже элемента управления NameTextBlockдля курса установлено значение [[EMPTY] », и через некоторое время выполняется строка с пометкой =======>, что приводит к ошибке.

В нескольких примерах, которые я видел, используется то, что кажетсясинхронный метод Get, но, похоже, его уже нет (и я бы не стал его использовать).

string name = "EMPTY";
        try
        {
            _fbClient.GetCompleted +=
            (o, e) =>
            {
                if (e.Error == null)
                {
                    var result = (IDictionary<string, object>)e.GetResultData();
                    //Dispatcher.BeginInvoke(() => MyData.ItemsSource = result);
                    var tempname = (string)result["name"];
                    name = (string)result["name"];
                    NameTextBlock.Text = "[" + name + "]";
                }
                else
                {
                    MessageBox.Show(e.Error.Message);
                }
            };

            _fbClient.GetAsync("/me");
 //======>      NameTextBlock.Text = "[" + name + "]";


        }
        catch
        {
            MessageBox.Show("Failed.. deal with issues.");
        }
        finally
        {
            NameTextBlock.Text = "[" + name + "]";
        }

Ответы [ 2 ]

1 голос
/ 07 июля 2011

У вас проблема с сочетанием условия гонки , а также с тем, что не-Gui-поток пытается изменить элемент интерфейса (я забыл правильный термин для этого).

В WPF вы используете шаблон Диспетчер для решения второй проблемы. В Winforms вы используете шаблон InvokeRequired .

Для борьбы с условиями гонки ... перед вызовом

_fbClient.GetAsync("/me");

Установите для NameTextBlock.Text значение «loading ...» или «fetching ...» или что-то в этом роде. Таким образом, когда асинхронный вызов завершается, он может заполнить текстовое поле правильными деталями. Вы также можете изменить стиль, чтобы сделать его более понятным для пользователя (например, серый при загрузке и ярко-красный при наличии результата). То, что вы делаете сейчас, предполагает, что к тому времени, когда вы установите текстовое поле для переменной name, событие (асинхронный вызов) уже завершено. Это может или не может иметь место!

Вообразите это более упрощенным способом. Два человека в гараже. Вы отправляете одного, чтобы открыть дверь гаража, другого, чтобы вести фургон в гараж. В вашем текущем коде парень, ведущий фургон, въезжает в гараж, не проверяя и не заботясь, открыта ли дверь гаража.

Следующая у вас проблема - Thread Safety . Переменная «name» может считываться и присваиваться одновременно, что означает, что операция чтения может работать с энергозависимой памятью и может вызвать ошибку / проблему, особенно в больших масштабах!

Я бы посоветовал вам взглянуть на Синхронизация потоков , чтобы получить лучшее представление.

Много информации, чтобы переварить там, извините. Надеюсь, это поможет, хотя!

0 голосов
/ 08 июля 2011

У вас есть ответ в предоставленном вами фрагменте кода.
Используйте метод Dispatcher.BeginInvoke следующим образом:

Dispatcher.BeginInvoke(() => NameTextBlock.Text = "[" + name + "]");
...