0 / 0 / 0
Регистрация: 30.06.2018
Сообщений: 1
1

Как изменить текст на форме из дочернего потока, когда в основном потоке ожидается завершение дочернего

30.06.2018, 17:14. Показов 1782. Ответов 1
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Идея следующая.
в основном потоке вызывают метод класса в другом потоке.
Причем необходимо:
1. чтобы пока работает дочерний поток форма не зависала
2. чтобы основной поток не выполнял дальше код, пока не завершится последний
3. чтобы из метода другого класса изменить, например, label на форме.

в основном потоке по кнопке вызывается метод объекта класса. для ожидания использую AutoResetEvent
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        public void SetTextSafe(string newText)
        {
            if (label9.InvokeRequired) label9.Invoke(new Action<string>((s) => label9.Text = s), newText);
            else label9.Text = newText;
        }
        public static AutoResetEvent waitHandler = new AutoResetEvent(false);
        private void button1_Click(object sender, EventArgs e)
        {
                Thread myThread = new Thread(logsObj.GetParsingLines);
                
                myThread.Start();
                waitHandler.WaitOne();
 
                ...код основного потока
         }
в методе класса у меня некий цикл, в котором выполняются некоторые операции. а в начале цикла я вызываю SetTextSafe из формы Form1 для изменения label9. После цикла я через waitHandler даю команду основному поток на продолжение.
C#
1
2
3
4
5
6
7
8
foreach (var f in files)
{
        Program.f1.SetTextSafe(f);
        ...начало кода
        ...конец кода
 
}
Form1.waitHandler.Set();
но сейчас у меня работает либо ожидание завершения дочернего потока без изменения label, либо изменения label, но без ожидания завершения дочернего потока.

вместе приводит к бесконечному зависанию. видимо, основной поток ждет, а ему приходит команда изменения label в основном потоке. и в итоге основной поток ожидает завершения второго потока, а второй поток ждет, пока изменится label.


как мне реализовать три пункта выше?

работает через отмену проверки System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; но это не очень хороший вариант

Спасибо!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.06.2018, 17:14
Ответы с готовыми решениями:

Нотификация объекта в основном потоке из дочернего потока
Проблема такая: имеется объект типа А в котором создается объект типа Б (вложенный). В классе Б...

Завершение основной программы из дочернего потока _beginthread
Подскажите пожалуйста команду, которая закрывает основную программу из созданного потока

Завершение дочернего процесса
Подскажите как правильно обработать завершение программы при вызове родителем QProcess::close()...

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

1
Эксперт .NET
6433 / 3965 / 1583
Регистрация: 09.05.2015
Сообщений: 9,284
30.06.2018, 17:38 2
И зачем такой геморрой? Используйте BackgroundWorker... Текст в форме можно будет обновлять через ReportProgress, так же есть событие завершения работы...

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
        private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }
 
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            foreach (var f in files)
            {
                backgroundWorker1.ReportProgress(0, f);
                //...начало кода
                //...конец кода
            }
        }
 
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label1.Text = (string)e.UserState;
        }
 
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //...код основного потока
        }
Или вообще

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        private async void button1_Click(object sender, EventArgs e)
        {
            IProgress<string> progress = new Progress<string>((p) => label1.Text = p);
 
            string[] files = new[] { "1", "2", "3" };
 
            await Task.Run(() =>
                {
                    foreach (var f in files)
                    {
                        progress.Report(f);
                        //...начало кода
                        //...конец кода
                    }
                });
 
            //...код основного потока
            MessageBox.Show("Done!");
        }
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.06.2018, 17:38
Помогаю со студенческими работами здесь

Корректное завершение дочернего процесса
Я тестирую оконную программу - открываю и закрываю её несколько раз. Иногда программа завершается с...

Завершение дочернего процесса по ошибке
Например, я запускаю дочерний процесс 1.ехе и ожидаю его окончания: #include &lt;windows.h&gt; #include...

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

Как изменить параметр дочернего обьекта?
Вот у меня есть префаб, который я Instantiate. Мне нужно обратится к вложеному в елементу...


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

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru