С наступающим Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# Windows Forms
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
meksik
202 / 171 / 67
Регистрация: 04.10.2014
Сообщений: 839
1

Вывод итератора цикла в отдельной строке в textBox без зависания программы

12.10.2014, 13:03. Просмотров 888. Ответов 18
Метки нет (Все метки)

Всем привет) Меня очень сильно сбивает с толку работа с потоками, поэтому хочу на простом примере разобрать эту тему, надеюсь вы поможете. Смотрел в гугле подобные примеры, но все равно ничего не понял, хочу вот именно на своем примере разобрать.
Вот код, надо слелать так, чтоб при работе цикла программа не зависала
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
namespace WindowsFormsApplication8
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        public void Method() 
        {
            int i = 0;
            while (i < 10000) 
            {
                textBox1.Text += i.ToString() + Environment.NewLine;
                i++;
            }
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            Method();
        }
    }
}
Заранее спасибо всем)
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.10.2014, 13:03
Ответы с готовыми решениями:

Копирование файлов с ProgressBar без зависания программы
Кто знает как можно копировать файлы с показом на прогрессбаре и без зависания...

Вывод суммы в textbox без кнопок
Доброго времени суток! Нужно выводить постоянно в текстовое поле данные. Не...

Вывод рандомного массива без повторений в TextBox
В TextBox рандомно вывожу один из элементов массива. При нажатии на кнопку...

Ждать завершения потока (без зависания формы)
Здравствуйте товарищи! Столкнулся с такой вот проблемой. Пишу программу,...

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

18
Darth Coder
281 / 262 / 107
Регистрация: 10.06.2011
Сообщений: 696
12.10.2014, 14:06 2
Используй Background Worker, например
0
meksik
202 / 171 / 67
Регистрация: 04.10.2014
Сообщений: 839
12.10.2014, 14:08  [ТС] 3
Darth Coder, это как вариант, но я хотел с примером использования Thread и делегата)

Добавлено через 29 секунд
и Invoke
0
Darth Coder
281 / 262 / 107
Регистрация: 10.06.2011
Сообщений: 696
12.10.2014, 14:24 4
http://msdn.microsoft.com/ru-ru/library/0b1bf3y3(v=vs.110).aspx

Добавлено через 1 минуту
http://professorweb.ru/my/csharp/thread_and_files/1/1_2.php
0
meksik
202 / 171 / 67
Регистрация: 04.10.2014
Сообщений: 839
12.10.2014, 14:31  [ТС] 5
Darth Coder, я не просил давать мне ссылки, видел я уже все это, мне нужно реализовать мой пример, тогда только я смогу понять что к чему

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
namespace WindowsFormsApplication8
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        public delegate void ProcessDelegate(int i);
 
 
        public void Method(int i) 
        {
            textBox1.Text += i.ToString() + Environment.NewLine;
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy != true)
            {
                backgroundWorker1.RunWorkerAsync();
            }
        }
 
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            while (i < 10000)
            {
                if (textBox1.InvokeRequired)
                {
                    textBox1.Invoke(new ProcessDelegate(Method), new object[] { i });
                }
                i++;
            }
        }
 
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("Done!");
        }
 
    }
}
сделал так, но у меня цикл бесконечный выходит

Добавлено через 1 минуту
хотя нет не бесконечный, если убавить до 100, то заканчивается, но выводит только от 0 до 14, не понимаю почему
0
Mikant
1282 / 955 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
12.10.2014, 14:36 6
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
namespace WindowsFormsApplication5 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }
        
        public void Method(object state) { // state - для удовлетворения сигнатуре WaitCallback
                                           // для нас бесполезно
 
            var action = new Action<int>(value => { // отделим метод, непосредственно изменяющий графику
                textBox1.Text += value + Environment.NewLine; // меняем что-то на графике
                //Application.DoEvents();
            });
 
            int i = 0;
            while (i < 10000) {
                if (InvokeRequired) { // если нам действительно требуется вызвать Invoke у формы
                                      // например, если мы обращаемся к ней из другого потока
 
                    Invoke(action, i); // для работы с формой из отдельного потока,
                                       // входим в контекст синхронизации основного потока gui,
                                       // передав метод action на исполнение + параметр i для него
 
                    //Application.DoEvents();
                    Thread.Sleep(1); // на миллисекунду прекращаем насиловать графику, чтобы
                                     // до следующего вызова Invoke у приложения была возможность,
                                     // например, перерисоваться и перемасштабироваться. можно было с
                                     // тем же успехом оставить Application.DoEvents внутри (или вне) Invoke,
                                     // чтобы заставить программу выполнить все свои рутинные дела
                                     // ДО следующего Invoke
 
                } else // иначе, вызываем наш метод в обыкновенном, синхронном режиме
                    action.Invoke(i); // то же, что и action(i) - вызываем метод action с параметром i
                                      // мне просто симметрия такой записи нравится)
 
                i++;
            }
        }
 
        private void button1_Click(object sender, EventArgs e) {
            ThreadPool.QueueUserWorkItem(Method); // вызываем долгий метод в отдельном потоке
                                                  // (из пула потоков)
        }
    }
}
останется справиться с тем, этот метод требуется останавливать перед закрытием окна
в вообще пример отвратительный: за такой код можно всякое поотрывать: какой смысл спамить на графику с такой частотой??
1
insite2012
Модератор
Эксперт .NET
4865 / 3818 / 1096
Регистрация: 12.10.2013
Сообщений: 11,095
Записей в блоге: 2
12.10.2014, 14:38 7
meksik, сейчас будет вам пример... Даже не один, а три в одном))) Немного подождите...
0
meksik
202 / 171 / 67
Регистрация: 04.10.2014
Сообщений: 839
12.10.2014, 14:49  [ТС] 8
Mikant, спасибо буду разбираться) много непонятного) а пример такой для того, чтоб реально увидеть работу фонового потока в деле)
insite2012, жду и ещё как жду)

Добавлено через 7 минут
мой вариант тоже сработал, когда убрал Environment.NewLine)
0
insite2012
Модератор
Эксперт .NET
4865 / 3818 / 1096
Регистрация: 12.10.2013
Сообщений: 11,095
Записей в блоге: 2
12.10.2014, 14:56 9
Лучший ответ Сообщение было отмечено meksik как решение

Решение

meksik, вот, разбирайте...
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
using System.Threading;
using System.Threading.Tasks;
 
namespace ThreadsTest
{
    public partial class Form1 : Form
    {
        delegate void MyDelegate();
        public Form1()
        {
            InitializeComponent();
            btnStartDelegate.Click += new EventHandler(btnStartDelegate_Click);
            btnStartThread.Click += new EventHandler(btnStartThread_Click);
            btnStartTask.Click += new EventHandler(btnStartTask_Click);
        }
        //Запуск через класс Task
        void btnStartTask_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() =>
                {
                    int i = 0;
                    while (true)
                    {
                        this.BeginInvoke((Action)(() =>
                        {
                            txtResult3.Text = i.ToString();
                        }));
                        i++;
                        Thread.Sleep(100);
                    }
                });
        }
        //Запуск через класс Thread
        void btnStartThread_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(new ThreadStart(MethodForThread));
            t.IsBackground = true;
            t.Start();
        }
        //Запуск через асинхронный делеагт
        void btnStartDelegate_Click(object sender, EventArgs e)
        {
            MyDelegate del = new MyDelegate(MethodForDelegate);
            IAsyncResult itfAR = del.BeginInvoke(null, null);
        }
        //Целевой метод для делегата
        void MethodForDelegate()
        {
            int i=0;
            while (true)
            {
                this.BeginInvoke((Action)(() =>
                    {
                        txtResult1.Text = i.ToString();
                    }));
                i++;
                Thread.Sleep(100);
            }
        }
        //Целевой метод для потока
        void MethodForThread()
        {
            int i = 0;
            while (true)
            {
                this.BeginInvoke((Action)(() =>
                {
                    txtResult2.Text = i.ToString();
                }));
                i++;
                Thread.Sleep(100);
            }
        }
        
    }
}
На всякий случай вот архив с проектом.
1
Вложения
Тип файла: rar ThreadsTest.rar (41.4 Кб, 8 просмотров)
meksik
202 / 171 / 67
Регистрация: 04.10.2014
Сообщений: 839
12.10.2014, 15:07  [ТС] 10
insite2012, спасибо огромное)

Добавлено через 7 минут
insite2012, вопрос, почему с Task настолько все проще и почему он не юзается вместо Thread повсеместно?
0
insite2012
Модератор
Эксперт .NET
4865 / 3818 / 1096
Регистрация: 12.10.2013
Сообщений: 11,095
Записей в блоге: 2
12.10.2014, 15:09 11
Цитата Сообщение от meksik Посмотреть сообщение
почему он не юзается вместо Thread повсеместно?
Он есть в .NET4.0 и выше. А если целевая платформа ниже, то его там нет. Да и знать потоковые примитивы тоже полезно.
Так же следует учесть, что в Task запускается фоновый поток (всегда). А если нужен НЕ фоновый, а основной? Тогда вот используется Thread.
1
Mikant
1282 / 955 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
12.10.2014, 15:19 12
insite2012,
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        void btnStartTask_Click(object sender, EventArgs e) {
            Task.Factory.StartNew(() => {
                    int i = 0;
                    while (true) {
                        this.BeginInvoke((Action)(() => {
                            Debug.Assert(string.IsNullOrEmpty(txtResult3.Text) || txtResult3.Text == (i - 1).ToString());
                            txtResult3.Text = i.ToString();
                            Thread.Sleep(150); // усложним задачу
                        }));
                        i++;
                        Thread.Sleep(100);
                    }
                });
        }
то есть, после определения времени тела изменяющего метода, появляется осмысленность числа 100. что наводит на очень "нехорошие" мысли
0
meksik
202 / 171 / 67
Регистрация: 04.10.2014
Сообщений: 839
12.10.2014, 15:24  [ТС] 13
insite2012, все понятно)
0
insite2012
Модератор
Эксперт .NET
4865 / 3818 / 1096
Регистрация: 12.10.2013
Сообщений: 11,095
Записей в блоге: 2
12.10.2014, 15:26 14
Mikant, а к чему это?
0
Mikant
1282 / 955 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
13.10.2014, 04:46 15
insite2012, к тому что пропагандировать использование BeginInvoke не стоит

Добавлено через 6 минут
... в данном случае не стоит, т.к. может потянуть за собой ещё бОльшие проблемы
0
insite2012
Модератор
Эксперт .NET
4865 / 3818 / 1096
Регистрация: 12.10.2013
Сообщений: 11,095
Записей в блоге: 2
13.10.2014, 05:05 16
Цитата Сообщение от Mikant Посмотреть сообщение
пропагандировать использование BeginInvoke не стоит
Mikant, да вы что? Ну так просветите нас, подскажите, как вы намереваетесь обращаться к пользовательскому интерфейсу из другого потока выполнения? Вы знаете какой-то другой способ?
0
Mikant
1282 / 955 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
13.10.2014, 13:13 17
insite2012, да. пример выше
0
insite2012
Модератор
Эксперт .NET
4865 / 3818 / 1096
Регистрация: 12.10.2013
Сообщений: 11,095
Записей в блоге: 2
13.10.2014, 15:44 18
Цитата Сообщение от Mikant Посмотреть сообщение
да. пример выше
А в чем разница? В том что вы проверяете необходимость маршаллинга из дополнительного потока в поток GUI? Так это известно, но не думаю, что это так уж необходимо...
Кстати, да, обычно я тоже использую Invoke((Action){}));
просто в данном случае что-то не так набралось.
0
Mikant
1282 / 955 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
13.10.2014, 22:47 19
insite2012, нет, дело совсем не в InvokeRequired. разница как раз в Invoke|BeginInvoke (что, обычно, дольше набирать)
в первом случае мы получим вызов метода обновления в тот же момент, что произойдёт синхронизация, а вот во втором "никто ничего не обещает": даже последовательность вывода чисел на экран легко может быть нарушена (как я показал в примере выше): 1-3-2 - и всё будет зависеть от звёзд...
0
13.10.2014, 22:47
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.10.2014, 22:47

Как сделать задержку в программе без зависания формы
Доброго времени суток :) Никак не получается решить одну задачу. Допустим,...

Как приостановить работу приложения без его зависания
Как сделать нормальную паузу в C#, чтобы она не вешала основной поток?...

Sleep без зависания программы
Как выполнить sleep без зависания программы?


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru