[ Полезный рекламный блок ]
Попробуйте свои силы в игре, где ваши навыки программирования на C# станут решающим фактором. Переходите по ссылке 🔰.
В C# Windows Forms, существует несколько способов обновления графического интерфейса из другого потока. Рассмотрим два наиболее распространенных подхода.
Использование метода Invoke()
Метод Invoke() позволяет выполнить делегат (метод) в контексте потока, в котором был создан объект управляющего элемента (control). Для того чтобы обновить графический интерфейс из другого потока, необходимо создать делегат, который будет содержать код, выполняющий необходимые изменения интерфейса, и затем вызвать метод Invoke() на объекте управляющего элемента, передав ему созданный делегат в качестве параметра:
1 2 3 4 5 6 |
// Running on the worker thread string newText = "abc"; form.Label.Invoke((MethodInvoker)delegate { // Running on the UI thread form.Label.Text = newText; }); |
Рассмотрим еще один простой пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
private void button1_Click(object sender, EventArgs e) { RunTask(); } void RunTask() { Task task = Task.Run(() => { for (int i = 0; i < 30; i++) { Thread.Sleep(1000); this.Invoke(new EventHandler(delegate { label1.Text = i.ToString(); })); } } ); } |
При нажатии на кнопку ‘button1’, происходит асинхронное циклическое присваивание инкриминируемого значения в ‘label1’ , с задержкой в 1 секунду.
Использование метода BeginInvoke()
Метод BeginInvoke() позволяет выполнить делегат асинхронно, т.е. не блокируя главный поток. Этот метод возвращает объект типа IAsyncResult, который можно использовать для проверки статуса выполнения асинхронной операции:
1 2 3 4 5 6 7 8 9 10 11 |
private void UpdateTextBox(string text) { if (textBox1.InvokeRequired) { textBox1.BeginInvoke(new Action<string>(UpdateTextBox), text); } else { textBox1.Text = text; } } |
В этом примере метод UpdateTextBox() вызывается с аргументом text. Если вызов происходит из другого потока, то метод BeginInvoke() используется для выполнения делегата в контексте потока, в котором был создан объект управляющего элемента (control). Если вызов происходит из того же потока, что и управляющий элемент, то метод выполняет непосредственно код в блоке else.
В метод BeginInvoke() передается делегат, который содержит метод UpdateTextBox() и его аргументы. В этом примере используется лямбда-выражение для создания делегата:
1 2 3 |
textBox1.BeginInvoke((Action)(() => { textBox1.Text = text; })); |
Обратите внимание, что перед вызовом метода BeginInvoke() следует проверить свойство InvokeRequired у управляющего элемента, чтобы убедиться, что вызов происходит из другого потока:
1 2 3 4 5 6 7 8 |
if (textBox1.InvokeRequired) { textBox1.BeginInvoke(new Action<string>(UpdateTextBox), text); } else { textBox1.Text = text; } |
Важно помнить, что при использовании метода BeginInvoke() следует обеспечить защиту доступа к общим данным, которые могут быть изменены из разных потоков, например, с помощью блокировки (lock).
Я надеюсь, что вам понравилось читать эту статью, и она оказалась легкой для понимания. Пожалуйста, дайте мне знать, если у вас есть какие-либо комментарии или исправления.
Так же вам может быть интересна предыдущая статья — Как сохранить изображение из Picturebox.
Вы хотите научится писать код на языке программирования C#?
Создавать различные информационные системы, состоящие из сайтов, мобильных клиентов, десктопных приложений, телеграмм-ботов и т.д.
Переходите к нам на страницу Dijix и ознакомьтесь с условиями обучения, мы специализируемся только на индивидуальных занятиях, как для начинающих, так и для более продвинутых программистов. Вы можете взять как одно занятие для проработки интересующего Вас вопроса, так и несколько, для более плотной работы. Благодаря личному кабинету, каждый студент повысит качество своего обучения, в вашем распоряжении:
- Доступ к пройденному материалу
- Тематические статьи
- Библиотека книг
- Онлайн тестирование
- Общение в закрытых группах
Живи в своем мире, программируй в нашем.