Сведения о вопросе

Kirushaa

10:27, 5th August, 2020

Теги

В WinForms, почему вы не можете обновить элементы управления UI из других потоков?

Просмотров: 504   Ответов: 2

Я уверен, что для этого есть хорошая (или, по крайней мере, приличная) причина. Что это?



  Сведения об ответе

lool

05:58, 29th August, 2020

Я думаю, что это блестящий вопрос - и я думаю, что есть потребность в лучшем ответ.

Конечно, единственная причина заключается в том, что там есть ли что-то в рамках где-то это не очень потокобезопасно.

Что "something" - это почти каждый отдельный элемент экземпляра в каждом отдельном элементе управления в System.Windows.Forms.

В документации MSDN для многих элементов управления в System.Windows.Forms, если не для всех из них, говорится: "все открытые статические (Общие в Visual Basic) члены этого типа потокобезопасны. Все члены экземпляра не гарантируют потокобезопасности."

Это означает, что члены экземпляра, такие как TextBox.Text {get; set;} , не являются реентерабельными .

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

[Редактировать]

Хотя этот вопрос задает только "why" вот ссылка на статью, которая объясняет "how":

Как сделать потокобезопасным звонки на Windows формы контроля MSDN

http://msdn.microsoft.com/en-us/library/ms171728.aspx


  Сведения об ответе

PROGA

04:03, 21st August, 2020

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

Для exmaple ваш вторичный поток может пытаться обновить элемент управления UI, но элемент управления UI будет ждать освобождения ресурса, заблокированного вторичным потоком, поэтому оба потока в конечном итоге ждут завершения работы друг друга. Как уже отмечали другие, эта ситуация не является уникальной для кода UI, но является особенно распространенной.

В других языках, таких как C++, вы можете попробовать сделать это (без исключения, как в WinForms), но ваше приложение может зависнуть и перестать отвечать на запросы в случае возникновения взаимоблокировки.

Кстати, вы можете легко сказать потоку UI, что хотите обновить элемент управления, просто создайте делегат, а затем вызовите (асинхронный) метод BeginInvoke для этого элемента управления, передав ему свой делегат. E.g.

myControl.BeginInvoke(myControl.UpdateFunction);

Это эквивалентно выполнению C++ / MFC PostMessage из рабочего потока


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться