Подтвердить что ты не робот

Можете ли вы получить доступ к элементам пользовательского интерфейса из другого потока? (не задано)

Я вижу много потоков в google/здесь, обновляя элемент пользовательского интерфейса из другого потока.

Что делать, если я хочу просто установить значение флажка?

Могу ли я сделать это, не делая ничего особенного?

4b9b3361

Ответ 1

Изменить. Кажется, мне нужно вернуть то, что я написал раньше. Пробовал следующее:

Добавлено текстовое поле с именем myTextBox и попыталось получить значение свойства Text:

Thread t = new Thread(
    o =>
    {
        Thread.Sleep(2000);                    
        string value = myTextBox.Text;
        Thread.Sleep(2000);
    });
t.Start();

И похоже, что приложение (WPF) падает через 2 секунды. Использование диспетчера работает:

Thread t = new Thread(
    o =>
    {
        Thread.Sleep(2000);
        myTextBox.Dispatcher.BeginInvoke(
            (Action)(() => { string value = myTextBox.Text; }));
        Thread.Sleep(2000);
    });
t.Start();

Таким образом, вам все равно нужно пройти поток диспетчера при чтении значений из компонентов GUI, по крайней мере в WPF.

Второе редактирование. Это улучшается. По-видимому, повторение эксперимента для классических WinForms показывает, что он работает, чтобы прочитать свойство Text, не используя Invoke/BeginInvoke. Интересно, что, похоже, что настройка свойства работает нормально (без вызова), хотя я ставлю его не потокобезопасным, и приложение почему-то не жалуется.

Нижняя строка. Хорошая идея в любом случае использовать диспетчера при взаимодействии с компонентами GUI из других потоков, поскольку это гарантирует, что чтение/запись сериализуется в один поток, и поэтому у вас есть нет проблем с безопасностью потока.

Ответ 2

Можете ли вы получить доступ к элементам пользовательского интерфейса из другого потока? (не задано)?

Нет.

Вот сделка. Элементы пользовательского интерфейса имеют очень строгие требования к привязке к потоку. Это означает, что вы можете получить доступ только к элементу из потока, на котором он находится. Это включает в себя все виды доступа, включая простые чтения. 1

Это может сработать для простых геттеров свойств, но его воспринимаемая безопасность будет случайным результатом того, как был реализован конкретный контроль. Поскольку экземпляры Control имеют сходство потоков, они потенциально могут использовать технологии локального хранения потоков, чтобы сохранить некоторые из их состояний, которые, конечно же, не были бы совместимы с разными потоками. Или что, если значение, которое вы пытаетесь прочитать, находится в полузасушливом состоянии? Невозможно синхронизировать доступ к этому чтению, поскольку запись может происходить внутри кода, который у вас нет. И все же это игнорирует проблемы с тонкой памятью, которые могут возникнуть.

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


1 За этим правилом очень мало исключений. Использование методов ISynchronizeInvoke является одним из таких исключений.

Ответ 3

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

Ответ 4

просто прочитайте значение, как обычно. Только для обновления элемента управления вам необходимо переключиться на поток графического интерфейса.