Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
Villiya
0 / 0 / 0
Регистрация: 13.01.2010
Сообщений: 35
1

ProgressBar не хочет работать из потока

07.01.2012, 20:43. Просмотров 2413. Ответов 16
Метки нет (Все метки)

помогите пожалуйста, не пойму что делаю не так, на форму закинуты прогрессбар и backgroundWorker и имеется такой код
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
private void CalcBtn_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
           
        }
       
        public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 100; i++)
            {
 
               /////данный кусок должен остаться неизменным
                CFirDoc p = new CFirDoc(id);               
                double TotalSeconds = p.Go();
                Form1.cdoc = p;
                ////
                
 
                backgroundWorker1.ReportProgress(i);
            }           
        }
 
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }
 
        public void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("Работа завершена");
        }
и вроде как операция выполняется, но прогрессбар остается неподвижным, при этом если написать
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
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 100; i++)
            {
                ///вместо необходимого моего куска
                for (int j = 0; j < 10000000; j++) ;
 
 
                backgroundWorker1.ReportProgress(i);                               
            }
        }
 
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }
 
       
        private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }
 
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            
                MessageBox.Show("Работа завершена");
        }
то все работает и прогрессбар движется? что я делаю не так?
или может лучше использовать
C#
1
2
 var thread = new Thread();
            thread.Start();
но как тогда в новом потоке правильно запустить
C#
1
2
3
CFirDoc p = new CFirDoc(id);               
                double TotalSeconds = p.Go();
                Form1.cdoc = p;
и прикрутить к нему прогрессбар?

не отправляйте пожалуйста к литературе, уже было много перечитано, но что-то ничего не помогает
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.01.2012, 20:43
Ответы с готовыми решениями:

Как работать с progressbar из другого потока
Сразу после начала работы программы вылетает такая ошибка &quot;Дополнительные сведения: Вызывающий...

Аварийное закрытие программы: ProgressBar с использованием дополнительного потока
В WPF набрал такой простенький пример с применением дополнительного потока: namespace TKControls {...

Шаг ProgressBar не из фонового потока
Можно ли каким-то образом сделать шаг в ProgressBar'e если он создан в фоновом потоке, а я хочу...

Заполнение ProgressBar посредством потока
Добрый вечер! Такое дело: я пишу программу по учёту документов, и в моей базе находятся около 24...

Ошибка доступ к элементу ProgressBar не из того потока, в котором он был создан
Здравствуйте друзья. Cross-thread operation not valid: Control 'progressBar1' accessed from a...

16
kolorotur
Эксперт .NET
11188 / 9115 / 2299
Регистрация: 17.09.2011
Сообщений: 15,659
Завершенные тесты: 1
07.01.2012, 20:48 2
У вас цикл заканчивается так быстро, что прогресс не успевает отрисовываться.
Это - первый признак в отсутствии надобности использования индикатора прогресса.
0
Villiya
0 / 0 / 0
Регистрация: 13.01.2010
Сообщений: 35
07.01.2012, 20:51  [ТС] 3
Цитата Сообщение от kolorotur Посмотреть сообщение
У вас цикл заканчивается так быстро, что прогресс не успевает отрисовываться.
цикл не заканчивается быстро эти 3 строчки кода
C#
1
2
3
CFirDoc p = new CFirDoc(id);               
                double TotalSeconds = p.Go();
                Form1.cdoc = p;
в самом лучшем случае расчитываются минуты 4
0
Talent
76 / 76 / 12
Регистрация: 07.01.2012
Сообщений: 167
09.01.2012, 02:16 4
C#
1
2
3
4
5
6
7
8
9
private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
            while (backgroundWorker1.IsBusy)
            {
                progressBar1.Increment(1);
                Application.DoEvents();
            }
}
Добавлено через 1 минуту
так он работает не из потока, но дает статус потока
1
VASSUV
MiThEoN
443 / 307 / 35
Регистрация: 31.10.2009
Сообщений: 505
Записей в блоге: 2
Завершенные тесты: 1
09.01.2012, 08:58 5
Цитата Сообщение от Villiya Посмотреть сообщение
вроде как операция выполняется, но прогрессбар остается неподвижным
У меня похожая штука была на visual studio, только с трэкбаром.
на самом деле все просто было. В режиме отладки не подвижным остается. А когда запускаешь exe-ку из bin\debug - тогжа все работает
1
hotkey
18 / 16 / 5
Регистрация: 06.09.2011
Сообщений: 51
09.01.2012, 13:57 6
попробуйте
C#
1
backgroundWorker1.WorkerReportsProgress = true;
1
Villiya
0 / 0 / 0
Регистрация: 13.01.2010
Сообщений: 35
09.01.2012, 21:49  [ТС] 7
Цитата Сообщение от Talent Посмотреть сообщение
C#
1
2
3
4
5
6
7
8
9
private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
            while (backgroundWorker1.IsBusy)
            {
                progressBar1.Increment(1);
                Application.DoEvents();
            }
}
Добавлено через 1 минуту
так он работает не из потока, но дает статус потока
если так, то прогрессбар при запуске "заполняется" очень быстро и останавливается, при этом процесс продолжает работать в фоне т.е. прогрессбар реально не отображает ход выполнения

Добавлено через 4 минуты
Цитата Сообщение от VASSUV Посмотреть сообщение
У меня похожая штука была на visual studio, только с трэкбаром.
на самом деле все просто было. В режиме отладки не подвижным остается. А когда запускаешь exe-ку из bin\debug - тогжа все работает
да, попробовала та запустить вроде процесс в прогрессбаре отображается, но только почему-то ОЧЕНЬ медленно, если так время растеза занимало минуты 4-5, то сейчас минут 20 и то за это время процесс выполняется только процентов на 15, есть ли возможность ускорить этот процесс?

Добавлено через 58 минут
возможно ли для данного случая использовать ThreadPool? если да, то каким образом будет выглядеть код? что-то типа такого?
C#
1
2
3
4
5
6
7
8
9
10
11
private void CalcBtn_Click(object sender, EventArgs e)
        {
           ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
           
        }
 static void ThreadProc(Object stateInfo) 
{
        CFirDoc p = new CFirDoc(id);               
                double TotalSeconds = p.Go();
                Form1.cdoc = p;
    }
но как тогда в этом случае отобразить ход вычислений на прогрессбаре? и вообще сообщить пользователю что вычисления закончены?
0
Димон_
136 / 104 / 9
Регистрация: 30.01.2011
Сообщений: 699
09.01.2012, 21:57 8
Не совсем по теме:
Я сделал, очень торопился, второй поток без использования backgroundWorker1. Есть переменная (глобальная) хранящая значение прогрессбара. Вот её-то я и инкрементирую в цикле второго потока. А кода включаю поток - включаю таймер обновления бара. Вот и все.
0
Villiya
0 / 0 / 0
Регистрация: 13.01.2010
Сообщений: 35
09.01.2012, 23:13  [ТС] 9
а можно хотя б приблизительный код увидеть?

Добавлено через 17 минут
понимаю что это выглядит как-то так
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
using System;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
 
namespace Program
{
    public partial class Form1 : Form
    {
        public int global1; // Используем для передачи одного из результатов фонового расчета в форму для отображения
 
        public Form1()
        {
            InitializeComponent();
            backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); 
            backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            backgroundWorker1.WorkerReportsProgress = true;
        }
 
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            toolStripProgressBar1.Value = e.ProgressPercentage; // Меняю данные прогрессбара
            toolStripStatusLabel1.Text = (String)e.UserState; // Меняю значение метки
        }
 
        // Расчет запускается при нажатии на кнопку button1
        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false; // На время расчета блокируем опасные кнопки
            toolStrip1.Enabled = false;
 
            backgroundWorker1.RunWorkerAsync(); // ЗАПУСКАЕМ ВЫЧИСЛЕНИЯ В ФОНОВОМ ПОТОКЕ!!!!
        }
 
        // Точка запуска фоновых расчетов
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            Calc(); // Вызываем метод с расчетами            
        }
 
        // Метод с расчетами
        private void Calc()
        {
            int bigNumber = 77777777;
            for (int i = 1; i < bigNumber; i++)
            {
                int n = (int)i * 100 / bigNumber; // вычисляем значение % для прогрессбара
                String s = "Выполнено " + n + "% расчета";
                backgroundWorker1.ReportProgress(n, s); // Отправляем данные в ProgressChanged
            }
            int global1 = i; // данные переменной global1 потом используем по окончании расчета для изменения формы 
            backgroundWorker1.ReportProgress(100, "Расчет завершен!"); // Выводим данные на форму
        }
        
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            button1.Enabled = true; // После окончания расчета разблокируем опасные кнопки
            toolStrip1.Enabled = true;
            label2.Text = "По окончанию расчета перешли к числу"  + global1;
            MessageBox.Show("Расчет окончен!");
        }
    }
}
но здесь опять же используется цикл для передачи данных в прогрессбар т.е. получается нсли я снасала пишу цикл и в нем передаю "процент" в прогрессбар, то он заполняется моментально, а расчет идет сам по себе, если расчет запускаю в цикле, то он считается лишнее кол-во раз, так где же прописать тогда вычисления, а где цикл для отображения процесса на прогрессбар?
0
Димон_
136 / 104 / 9
Регистрация: 30.01.2011
Сообщений: 699
09.01.2012, 23:14 10
Это в кнопке, запускающей действие
int progressBarValue =0;
объявлен в классе

C#
1
2
3
4
5
6
7
8
9
10
11
12
string name = lHandle[cbx_friendsBottom.SelectedIndex];
            this.progressBar1.Maximum = (int)numericUpDown2.Value*(int)numericUpDown3.Value - 1;
            int pause = (int)numericUpDown1.Value;
            int replay=(int) numericUpDown3.Value;
            int count =(int)numericUpDown2.Value;
            string text = textBox2.Text;
            progressBar1.Value = 0; 
            progressBarValue = 0;
            System.Threading.Thread t = new System.Threading.Thread(delegate() { ThreadOur(name, pause, replay, count, text); });
            t.IsBackground = true;
            t.Start();
            timer2.Enabled = true;
А вот в таймере:
C#
1
2
3
4
5
6
7
try { progressBar1.Value = progressBarValue; }
            catch 
            {
                progressBar1.Value = 0;
                progressBarValue=0;
                timer2.Enabled = false; 
            }
Добавлено через 1 минуту
Не смотри на то, как создан поток (это уже мое личное так сказать)
0
Villiya
0 / 0 / 0
Регистрация: 13.01.2010
Сообщений: 35
09.01.2012, 23:57  [ТС] 11
что не очень понятно что происходит с progressBarValue как вижу что объявляется
Код
 progressBarValue=0;
а в таймере
Код
 progressBar1.Value = progressBarValue;
, но где же происходит тогда изменение самого progressBarValue?
0
Casper-SC
Эксперт .NET
3980 / 1869 / 367
Регистрация: 27.03.2010
Сообщений: 5,219
Записей в блоге: 1
10.01.2012, 01:51 12
Villiya, твой код по идее работать должен, а то начали уже изобретать что-то. Свойству WorkerReportsProgress присвой true.
0
Villiya
0 / 0 / 0
Регистрация: 13.01.2010
Сообщений: 35
10.01.2012, 02:25  [ТС] 13
да, он работает, но работает сейчас очень медленно т.к. там в цикле 100 раз выполняется код
C#
1
2
3
CFirDoc p = new CFirDoc(id);               
                double TotalSeconds = p.Go();
                Form1.cdoc = p;
а если не в цикле его писать, то тогда прогрессбар работает сам по себе, а вычисления сами по себе, теперь дкмаю куда вставить эти 3 строчки чтоб они работали вместе и не 100 раз
0
Casper-SC
Эксперт .NET
3980 / 1869 / 367
Регистрация: 27.03.2010
Сообщений: 5,219
Записей в блоге: 1
10.01.2012, 03:08 14
Ну если бы знать что делает этот код, то можно было бы что-то придумать. И вообще нафиг нужен цикл? Используй свойства:
C#
1
2
            progressBar1.Style = ProgressBarStyle.Marquee;
            progressBar1.Style = ProgressBarStyle.Blocks;
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
        private void CalcBtn_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }
       
        public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
               //1 раз достаточно вызвать, знаю можно и по другому сделать,
               //но какая разница то? Пусть так будет
               backgroundWorker1.ReportProgress(0); 
               /////данный кусок должен остаться неизменным
                CFirDoc p = new CFirDoc(id);               
                double TotalSeconds = p.Go();
                Form1.cdoc = p;
        }
 
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Style = ProgressBarStyle.Marquee;
        }
 
        public void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressBar1.Style = ProgressBarStyle.Blocks;
            MessageBox.Show("Работа завершена");
        }
1
Димон_
136 / 104 / 9
Регистрация: 30.01.2011
Сообщений: 699
10.01.2012, 10:24 15
инкрементируются в ThreadOur() этом методе..
0
kolorotur
Эксперт .NET
11188 / 9115 / 2299
Регистрация: 17.09.2011
Сообщений: 15,659
Завершенные тесты: 1
10.01.2012, 10:33 16
Цитата Сообщение от Villiya Посмотреть сообщение
C#
1
double TotalSeconds = p.Go();
В методе p.Go() наверное отдельный поток запускается, да?
0
Villiya
0 / 0 / 0
Регистрация: 13.01.2010
Сообщений: 35
12.01.2012, 04:06  [ТС] 17
Цитата Сообщение от kolorotur Посмотреть сообщение
В методе p.Go() наверное отдельный поток запускается, да?
не совсем так, сам метод запускает просто вычисления - не поток, а вот этот метод уже необходимо запустить в новом потоке

Добавлено через 3 минуты
Цитата Сообщение от Casper-SC Посмотреть сообщение
И вообще нафиг нужен цикл?
в данном случае цикл использовался, по незнанию, только для отображения процесса в прогрессбаре, на самом деле он не несет никакой иной смысловой нагрузки
0
12.01.2012, 04:06
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.01.2012, 04:06

Как работать с ProgressBar
Всем привет ! вот код string http; int j = 0; for (int povtor = 0; povtor &lt;...

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

Изменить значение ProgressBar из потока
Доброго времени суток, форумчане. Необходима ваша помощь в правильной организации потоков. Есть...


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

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

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