Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
4 / 4 / 2
Регистрация: 29.10.2015
Сообщений: 76

Ручное создание вторичных потоков и операции с формой

22.06.2016, 14:22. Показов 1097. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день! Подскажите, пожалуйста по взаимодействию вторичных потоков и формы,
Ответы на 7 самых частых вопросы изучил, именно на мой случай ответа не нашел.

Создаю вторичный поток получения данных, и, пока он выполняется, в основном потоке идет постоянная смена label1.Text:
"Идет получение данных.
Идет получение данных..
Идет получение данных..." и т.д. пока созданный поток не завершится.


Однако, когда я пытаюсь в новосозданном потоке выполнить длительное действие, которое требует взаимодействия с Формой (через Control.BeginInvoke), созданной в вызывающем потоке (в примере в качестве длительного действия указана заглушка Thread.Sleep(5000), но допустим во вторичном потоке мне надо пройтись по 10-ти листбоксам, и в каждом по 50 000 записей),
в таком случае вызывающий поток перестает обновлять label1.Text
и постоянного обновления
"Идет получение данных.
Идет получение данных..
Идет получение данных..."

уже не происходит, а идет ожидание выполнения Thread.Sleep(5000) вторичного потока.

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



C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//---------------------------------------
//нажатие по кнопке вызывает новый поток и постоянно выводит в label1 текст
//Идет получение данных. 
//Идет получение данных..
//Идет получение данных... 
//и так по кругу пока поток не завершится (в конце нового потока isDone = true)
 
private void button3_Click(object sender, EventArgs e)
 {
        this.thread1 = new Thread(new ThreadStart(StartNewThread));
        thread1.Start();
 
        while (!isDone)
        {
            this.Invoke((Action)delegate
            {
                label1.Text = "Идет получение данных"+".";
                label1.Update();
                Thread.Sleep(100);
                label1.Text = "Идет получение данных" + "..";
                label1.Update();
                Thread.Sleep(100);
                label1.Text = "Идет получение данных" + "...";
                label1.Update();
                Thread.Sleep(100);
                label1.Text = "Идет получение данных";
                label1.Update();
                Thread.Sleep(100);
            });
        }
        
        label1.Text = "ПОТОК ЗАВЕРШЕН";
 
}
 
//точка входа в новый поток
//выполнив некотрую работу  (тут заглушка Thread.Sleep()), 
//надо вывести в ТекстБокс фразу "РАБОТА ЗАВЕРШЕНА", и только потом закрыть поток
 
public void StartNewThread()
{
    if (textBox1.InvokeRequired)
    {
        this.BeginInvoke((Action)delegate
        {
            //имитация длительного действия
            //пока выполняется этот код (в данном случае пауза)
            //значения в label1 перестают изменятся вызывающим потоком
 
            Thread.Sleep(5000);               
            textBox1.Text="РАБОТА ЗАВЕРШЕНА";
        });
    }
    else
    {
        Thread.Sleep(5000);               //пока выполняется этот код, значения в label1 перестают изменятся
        textBox1.Text="РАБОТА ЗАВЕРШЕНА";
    }    
    isDone = true;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
22.06.2016, 14:22
Ответы с готовыми решениями:

Ручное управление количеством потоков в ThreadPool
Картина такая: есть некое приложение, которое может внутри себя наплодить до 1к потоков через Task.Start, для общения с сетевыми девайсами....

Запретить доступ к методу из вторичных потоков
Здравствуйте. Пишу фреймворк для своих нужд, чем то похожий на Unity3d - в плане однопоточноной последовательности. Но на всякий случай...

Создание программы по поверке вторичных приборов
Попробую задать вопрос коректно и более понятно! Как и с помощью чего создать программу по поверке например видеографического...

6
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18286 / 14209 / 5368
Регистрация: 17.03.2014
Сообщений: 28,889
Записей в блоге: 1
22.06.2016, 22:59
ribastar, вызов Invoke() просит выполнить код в контексте UI потока. Двумя вещам сразу ни один поток заниматься не может. Поэтому количеcтво вызовов Invoke() лучше сводить к минимуму и выполнять как можно быстрее.
0
4 / 4 / 2
Регистрация: 29.10.2015
Сообщений: 76
23.06.2016, 09:13  [ТС]
Как же тогда правильно поступать (с точки зрения качественного кода), чтобы вторичный поток мог свободно и без помех вызывающему потоку получать доступ к элементам формы (хотя бы на чтение) и при этом вызывающий поток также делал свои дела с формой?
Чтобы два потока одновременно и параллельно работали с данными формы и не прерывали друг друга (процессорные автопрерывания на низком уровне не всчет), пусть и грязное чтение?
0
Эксперт .NET
 Аватар для Rius
13115 / 7676 / 1674
Регистрация: 25.05.2015
Сообщений: 23,418
Записей в блоге: 14
23.06.2016, 10:01
Запускаете поток, который называете "вторичным". В нём проводите все долгие операции.
Если нужно что-то отобразить в UI, это обязано выполниться за короткое время < 1 мс. Вот это быстрое обновление UI вызываете в контексте потока UI.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
23.06.2016, 10:08
Цитата Сообщение от ribastar Посмотреть сообщение
чтобы вторичный поток мог свободно и без помех вызывающему потоку получать доступ к элементам формы (хотя бы на чтение)
Поток должен работать с данными, а не с "элементами формы". Создайте модель данных и обращайтесь к ним из какого угодно потока. А GUI поток и формы нужны для взаимодействия с пользователем, а не для обработки данных.
0
4 / 4 / 2
Регистрация: 29.10.2015
Сообщений: 76
23.06.2016, 18:07  [ТС]
Storm23
интересно, кажется стало доходить! ты имеешь ввиду, что, допустим, вместо того чтобы вторым потоком брать данные напрямую из ЛистБоксов на форме, надо изначально в класс формы добавить указатель на другой класс, содержащий данные, которые потом передадутся в ЛистБоксы? и уже вторым потоком работать с данными не формы, а конкретных классов?
то есть впринципе никогда не стоит напрямую большие данные черпать прямо из формы?

Добавлено через 22 минуты
и всеже я до конца еще не разобрался,

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

Правильно ли я понимаю, что обновлять надпись в лэйбле стоит также во ВТОРОМ потоке, который вставляет данные в ЛистБокс, а не в первом (вызывающем)?


напоминаю у меня щяс так (обновление Лэйбла в первом потоке):
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//второй поток
public void StartNewThread()
{
if (listBox1.InvokeRequired)
            {
                this.Invoke((Action)delegate
                {
                    //в этот момент надпись  "ждем.", "ждем..","ждём..." перестаёт бегать
                    listBox1.Items.Clear();
                    
                    foreach (string partner in this.partners)
                    {
                        listBox1.Items.Add(partner);
                        //НЕУЖЕЛИ СЮДА НАДО ВСТАВЛЯТЬ ОБНОВЛЕНИЕ ЭТОЙ НАДПИСИ "Ждем..."???
                    }
                       isDone = true;
                });
            }
}
 
//первый поток
while (!isDone)
        {
            this.Invoke((Action)delegate
            {
                label1.Text = "ждём"+".";
                label1.Update();
                Thread.Sleep(100);
                label1.Text = "ждём" + "..";
                label1.Update();
                Thread.Sleep(100);
                label1.Text = "ждём" + "...";
                label1.Update();
                Thread.Sleep(100);
                label1.Text = "ждём";
                label1.Update();
                Thread.Sleep(100);
            });
        }
0
Эксперт .NET
 Аватар для Rius
13115 / 7676 / 1674
Регистрация: 25.05.2015
Сообщений: 23,418
Записей в блоге: 14
23.06.2016, 18:10
Цитата Сообщение от ribastar Посмотреть сообщение
//НЕУЖЕЛИ СЮДА НАДО ВСТАВЛЯТЬ ОБНОВЛЕНИЕ ЭТОЙ НАДПИСИ "Ждем..."???
Нет, сюда не надо. Не будет работать. UI не обновится до завершения метода в Invoke.
Надо заполнить список данных в отдельном потоке. А в потоке UI всего лишь подключить список к ListView.
И вообще, "Ждём..." - будет только замедлять.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.06.2016, 18:10
Помогаю со студенческими работами здесь

Связь потоков с формой
Поток должен изменять значение элементов в форме (2x richTextBox, CheckBox) Как это реализовать? Приведите пожалуйста пример с...

Работа с формой с помошью потоков
Добрый день! Извиняюсь, что вопрос глуп, но. Форма MainWindow создает и показывает форму Monitor mntr. В форме VideoWorked создается...

Ручное создание БД оракл
люди добрые! подскажите пожалуйста, каким образом правильно вручную создать БД. следовал по ссылке ниже. но не получилось. ...

Создание и завершение процессов и потоков. Приоритеты выполнения потоков
Здравствуйте. Буду очень раз если поможете понять,что конкретно нужно сделать в вот этом задании,пока особого представления о...

Ручное создание Window и Grid
Здравствуйте! Решила создать окно WPF с кнопкой, не на XAML, а на C#. Вот создано окно и кнопка, но не могу сообразить как ее отобразить в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru