Модераторы: gambit, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Опять progressbar, progressbar в потоке 
V
    Опции темы
maxnoskov
Дата 7.2.2007, 10:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 21.6.2006
Где: Мурманск

Репутация: нет
Всего: нет



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

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private Form2 LoadForm = new Form2();
        private void Form1_Load(object sender, EventArgs e)
        {
            sqLiteDataAdapter1.Fill(dataSet11, "first");
        }
        
        private void ProcessDo()
        {
            LoadForm.progressBar1.Invoke(new MethodInvoker(delegate()
            {
            for (; ; )
            {
                if (LoadForm.progressBar1.Value >= LoadForm.progressBar1.Maximum) LoadForm.progressBar1.Value = 0;
                LoadForm.progressBar1.Value++;
            }
        }));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            System.Threading.Thread thr = new System.Threading.Thread(ProcessDo);
            if (LoadForm == null) LoadForm = new Form2();
            LoadForm.Show();
            thr.Start();
            
            for (int i = 0; i < 100; i++)
            {
                DataRow NewDataRow = dataSet11.first.NewRow();
                dataSet11.first.Rows.Add(NewDataRow); 
            }
            sqLiteDataAdapter1.Update(dataSet11, "first");
            dataSet11.AcceptChanges();
            //ds.ReadXML(path);
            thr.Abort();
            LoadForm.Close();
            LoadForm.Dispose();
        }
    }


PM MAIL   Вверх
ivashkanet
Дата 7.2.2007, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 11
Всего: 149



Цитата

Код

            LoadForm.progressBar1.Invoke(new MethodInvoker(delegate()
            {
            for (; ; )
            {
                if (LoadForm.progressBar1.Value >= LoadForm.progressBar1.Maximum) LoadForm.progressBar1.Value = 0;
                LoadForm.progressBar1.Value++;
            }


 smile  smile  smile  smile  smile  smile 

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

Код

            while (true)
            {
                LoadForm.progressBar1.Invoke(new MethodInvoker(delegate()
                {

                    if (LoadForm.progressBar1.Value >= LoadForm.progressBar1.Maximum) LoadForm.progressBar1.Value = 0;
                    LoadForm.progressBar1.Value++;
                }));

                Thread.Sleep(100); // останавливаем поток на 1/10 секунды
            }



Это сообщение отредактировал(а) ivashkanet - 7.2.2007, 11:04
PM MAIL WWW ICQ   Вверх
maxnoskov
Дата 7.2.2007, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 21.6.2006
Где: Мурманск

Репутация: нет
Всего: нет



Тот же результат, появляется окно, но progressbar не бежит - мертвый
PM MAIL   Вверх
ivashkanet
Дата 7.2.2007, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 11
Всего: 149



Цитата
Код

            for (int i = 0; i < 100; i++)
            {
                DataRow NewDataRow = dataSet11.first.NewRow();
                dataSet11.first.Rows.Add(NewDataRow); 
            }
            sqLiteDataAdapter1.Update(dataSet11, "first");
            dataSet11.AcceptChanges();


Это называется чудеса на виражах:
Прогрессбар бежит в отдельном потоке, а вот тяжелая работа идет в потоке формы smile

Тебе нужно сделать наоборот: тяжелую работу вынести в отдельный поток, а прогресбар может даже бежать в той же самой форме
PM MAIL WWW ICQ   Вверх
maxnoskov
Дата 7.2.2007, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 21.6.2006
Где: Мурманск

Репутация: нет
Всего: нет



Если не сложно, можно пример относительно данного случая smile 
PM MAIL   Вверх
ivashkanet
Дата 7.2.2007, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 11
Всего: 149



Даааа, не так все было просто как мне казалось smile 
Код

    public partial class Form1 : Form
    {
        ProgressForm _pForm;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _pForm = new ProgressForm();
            _pForm.Show();
            _pForm.StartPBar();

            Thread thr = new System.Threading.Thread(ProcessDo);
            thr.Start();
        }

        private void ProcessDo()
        {
            //for (int i = 0; i < 100; i++)
            //{
            //    DataRow NewDataRow = dataSet11.first.NewRow();
            //    dataSet11.first.Rows.Add(NewDataRow);
            //}
            //sqLiteDataAdapter1.Update(dataSet11, "first");
            //dataSet11.AcceptChanges();

            long j = 10;

            for (long i = 0; i < 2000000000; i++)
            {
                j += i;
                j -= i;
            }

            EndJob();
        }

        private void EndJob()
        {
            this.Invoke(new MethodInvoker(delegate()
            {
                _pForm.Close();
                _pForm.Dispose();

                MessageBox.Show("Job is done");
            }));
        }
    }


    public class ProgressForm : Form
    {
        ProgressBar _progressBar;
        Thread _thread;

        public ProgressForm()
        {
            _progressBar = new ProgressBar();
            this.SuspendLayout();

            _progressBar.Dock = DockStyle.Fill;

            this.ClientSize = new System.Drawing.Size(200, 20);
            this.Controls.Add(_progressBar);
            this.Name = "ProgressForm";
            this.Text = "Processing, please wait";
            this.FormClosing += new FormClosingEventHandler(ProgressForm_FormClosing);

            this.ResumeLayout(false);
        }

        public void StartPBar()
        {
            _thread = new System.Threading.Thread(ProcessPBar);
            _thread.Priority = ThreadPriority.AboveNormal;
            _thread.Start();
        }

        private void ProcessPBar()
        {
            try
            {
                while (true)
                {
                    IncreasePBar();

                    Thread.Sleep(100);
                }
            }
            catch (ThreadAbortException) {/* Просто способ завершения потока */}
        }

        public void IncreasePBar()
        {
            this.Invoke(new MethodInvoker(delegate()
            {
                if (_progressBar.Value >= _progressBar.Maximum)
                    _progressBar.Value = 0;
                _progressBar.Value++;
            }));
        }

        void ProgressForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            // Закрываем поток
            _thread.Abort();
            _thread.Join();
        }
    }


Я бы не делал отдельную форму для прогрессбара, а поместил бы его в строку состояния, например.

P.S. Приму любые замечания по коду.
PM MAIL WWW ICQ   Вверх
maxnoskov
Дата 7.2.2007, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 21.6.2006
Где: Мурманск

Репутация: нет
Всего: нет



Спасибо большое, огромный респект. По поводу примечания, а как запхать progressbar в строку состояния. Я даже ни разу с таким не сталкивался
PM MAIL   Вверх
ivashkanet
Дата 7.2.2007, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 11
Всего: 149



Цитата(maxnoskov @  7.2.2007,  12:05 Найти цитируемый пост)
Спасибо большое, огромный респект

Не за что smile

Примечания:
1) Форму с баром нужно сделать поверх приложения. ShowDialog() не подходит, так как ждет завершения работы формы.
2) При закрытии основной формы вылетает эксепшин на IncreasePBar()ю Решение --- закрывать вторую форму при закрытии первой.
3) Вместо второго потока (для  прогресс бара) лучше использовать таймер

Цитата(maxnoskov @  7.2.2007,  12:05 Найти цитируемый пост)
Я даже ни разу с таким не сталкивался

Я тоже не пробовал. Но У MSDN, Word и др. эта хрень есть smile

Так же можно попробовать вместо формы использовать usercontrol (прогрессбар и немного места вокруг него, как на Винграде) и делать ему BringToFront()
PM MAIL WWW ICQ   Вверх
maxnoskov
Дата 7.2.2007, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 21.6.2006
Где: Мурманск

Репутация: нет
Всего: нет



Можно в принципе вынести progressbar в statusStrip и юзать ее на форме. Но так как основным потоком должен идти какой-то процесс - не прогресс, я не знаю как мне в основном потоке циклически запустить прогресс и как его убить - как я узнаю, что основной процесс уже завершился? 
PM MAIL   Вверх
ivashkanet
Дата 7.2.2007, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 11
Всего: 149



Цитата(maxnoskov @  7.2.2007,  14:08 Найти цитируемый пост)
Но так как основным потоком должен идти какой-то процесс - не прогресс

Этот процесс лучше выделить в отдельный поток
Цитата(maxnoskov @  7.2.2007,  14:08 Найти цитируемый пост)
как я узнаю, что основной процесс уже завершился

EndJob()
PM MAIL WWW ICQ   Вверх
Berserk
Дата 7.2.2007, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 14.12.2006
Где: Столица Донбасса - Горловка

Репутация: нет
Всего: 2



А если есть желание поработать с потоками, то можно кинуть на форму BackgroundWorker. Неплохо описано здесь. Можно код с примером скачать.
--------------------
  
PM MAIL ICQ   Вверх
maxnoskov
Дата 7.2.2007, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 21.6.2006
Где: Мурманск

Репутация: нет
Всего: нет



Решил проблему - вынес progressbar в statusStrip. Запускаю его по таймеру. А основной процесс в отдельном потоке. Когда основной процесс заканчивается - останавливаю таймер.
P.S. отдельная благодарность -  ivashkanet. Без него бы не справился smile 
PM MAIL   Вверх
ivashkanet
Дата 7.2.2007, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 11
Всего: 149



maxnoskov, о, оно самое.
Для закрытия вопроса положи сюда код, а.
PM MAIL WWW ICQ   Вверх
maxnoskov
Дата 9.2.2007, 10:19 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 21.6.2006
Где: Мурманск

Репутация: нет
Всего: нет



Конечно, закрываю вопрос:
Код

 public partial class Form1 : Form
    {
        private System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();//Создаем таймер
        Thread _thread1 = null;
        
        public Form1()
        {
            InitializeComponent();
         }
        
        private void button1_Click(object sender, EventArgs e)
        {
            timer2.Interval = 10;
            timer2.Start();
            _thread1 = new Thread(Process);
            _thread1.Start();
            this.Invoke(new MethodInvoker(delegate()
                  {
                      toolStripStatusLabel1.Text = "Подождите...";
                  }));
            
        }

        private void Thread_exit()
        {
            if (_thread1 != null)
            {
                  timer2.Stop();//Вырубаем таймер
                  this.Invoke(new MethodInvoker(delegate()
                  {
                      toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
                      toolStripStatusLabel1.Text = "Операция завершена";
                  }));
                 _thread1.Abort();//Убиваем поток
                _thread1.Join();
            }
            
        }

        void Process()//Здесь тот процесс, который будет выполнятся в дополнительном потоке
        {
            for (int i = 0; i < 50; i++)
            {
                DataRow NewDataRow = dataSet11.first.NewRow();
                dataSet11.first.Rows.Add(NewDataRow);
            }
            sqLiteDataAdapter1.Update(dataSet11, "first");
            dataSet11.AcceptChanges();
            Thread_exit();
            
        }
        
        private void timer2_Tick(object sender, EventArgs e)//Здесь работает прогрессбар
        {
            if (this.toolStripProgressBar1.Value + 1 == this.toolStripProgressBar1.Maximum)
                this.toolStripProgressBar1.Value = 0;
            else
                this.toolStripProgressBar1.Value++;
            Thread.Sleep(10);
        }
    }

Единственная проблема - это то, что другие объекты на форме являются активными. Ну например меню. Если не хочется, чтобы во время операции пользователь совершал другие действия - ну не смотрит он на прогрессбар или не хоче смотреть. Надо эти элементы закрывать. 
Всем спасибо за помощь
PM MAIL   Вверх
maxnoskov
Дата 15.2.2007, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 21.6.2006
Где: Мурманск

Репутация: нет
Всего: нет



Цитата(Berserk @ 7.2.2007,  15:19)
А если есть желание поработать с потоками, то можно кинуть на форму BackgroundWorker. Неплохо описано здесь. Можно код с примером скачать.

Да, с BackgroundWorker получилось даже красивее. Спасибо за ссылку.
Цитата

Единственная проблема - это то, что другие объекты на форме являются активными. Ну например меню. Если не хочется, чтобы во время операции пользователь совершал другие действия - ну не смотрит он на прогрессбар или не хоче смотреть. Надо эти элементы закрывать. 

А ларчик то просто открывается. В смысле проблемы нет - подвязываемся на FormClosing и делаем Enable = false для меню пока работает доп. поток 

Это сообщение отредактировал(а) maxnoskov - 15.2.2007, 14:32
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Разработка Windows Forms | Следующая тема »


 




[ Время генерации скрипта: 0.0651 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.