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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как сделать две формы, выполняющиеся в разных пото 
:(
    Опции темы
artstalker
Дата 7.5.2009, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 5.2.2009

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



Если упростить пример, то есть допустим метод, который создаёт вторую форму, и во время своего выполнения прогрессбар на форме №2 растёт.

 
Код

private void button10_Click(object sender, EventArgs e)
        {
            Form2 f2 = new Form2();
            f2.Show();
            for (int i = 0; i < 100; i++)
            {
                Thread.Sleep(100);
                f2.progressBar1.Value = i;
            }
        }
 



Форма 2 в таком случае зависает. Оно и понятно.

Тогда я придумал такой способ:

Form1:
 
Код

private void button10_Click(object sender, EventArgs e)
       {
            Form2 f2 = new Form2();
            f2.Show();
            ThreadPool.QueueUserWorkItem(Method, f2);          
        }
        void Method(object value)
        {
            for (int i = 0; i < 100; i++)
            {
                Thread.Sleep(100);
                (value as Form2).Invoke((async)(value as Form2).asyncmethod, i);
 
            }
 
        }
        delegate void async(object value);



Form2:


 
Код

public void asyncmethod(object value)
        {
            progressBar1.Value = (int)value;
        }


Можно ли сделать как-то проще?



Это сообщение отредактировал(а) artstalker - 7.5.2009, 14:19
PM MAIL   Вверх
Partizan
Дата 7.5.2009, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

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



поюзать BackgroundWorker? smile


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
artstalker
Дата 7.5.2009, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 5.2.2009

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



А как он может помочь? Ну кроме замены строчки 
Код

ThreadPool.QueueUserWorkItem(Method, f2);

на
Код

 backgroundWorker1.RunWorkerAsync(f2);

PM MAIL   Вверх
artstalker
Дата 7.5.2009, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 5.2.2009

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



А вот если мне надо сделать наоборот. Допустим есть метод который долго выполняется и из этого метода мне нужно создать форму так чтобы она не зависала, т.е. в параллельном потоке. Т.е. что-то наподобие этого:
Код

private void button10_Click(object sender, EventArgs e)
       {
             ThreadPool.QueueUserWorkItem(Method, this); 
           for (int i = 0; i < 100; i++)
            {
                Thread.Sleep(100);
                 
            }
           
                     
        }
        void Method(object value)
        {
           Form2 f2 = new Form2();
            f2.Show();
             
        }


Но если так написать, то форма 2 зависнет, так как Method выполнится и поток закроется.

Это сообщение отредактировал(а) artstalker - 7.5.2009, 18:20
PM MAIL   Вверх
-Mikle-
Дата 7.5.2009, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

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



Цитата(artstalker @  7.5.2009,  17:28 Найти цитируемый пост)
А как он может помочь?

Так, что он уже имеет всю синхронизацию с основным потоком.

вот, смотри:
Код


        Form2 progressForm;

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 100; i++)
            {
                if (backgroundWorker1.CancellationPending)
                {
                    e.Cancel = true;
                    break;
                }

                System.Threading.Thread.Sleep(200);
                backgroundWorker1.ReportProgress(i + 1);
            }

            if (!e.Cancel)
                e.Result = "Completed!";
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (progressForm != null && !progressForm.IsDisposed)
                progressForm.progressBar1.Value = e.ProgressPercentage;
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            btnStart.Enabled = true;
            btnCancel.Enabled = false;
            progressForm.Close();
            progressForm = null;

            if (e.Cancelled)
                MessageBox.Show("Operation has been canceled!");
            else
                MessageBox.Show("Result: " + Convert.ToString(e.Result));
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;

            btnStart.Enabled = false;
            btnCancel.Enabled = true;

            progressForm = new Form2();
            progressForm.Show(this);
            backgroundWorker1.RunWorkerAsync();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            backgroundWorker1.CancelAsync();
        }



--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
artstalker
Дата 7.5.2009, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 5.2.2009

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



А как мне сделать наоборот? Есть выполняющийся поток и из него надо как-то создать форму в другом потоке.

PM MAIL   Вверх
-Mikle-
Дата 8.5.2009, 09:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

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



Цитата(artstalker @  8.5.2009,  01:03 Найти цитируемый пост)
Есть выполняющийся поток и из него надо как-то создать форму в другом потоке

имхо, не хорошо создавать форму из другого потока в первом потоке. К чему это?


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
artstalker
Дата 8.5.2009, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 5.2.2009

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



Ну вот смотри. У меня есть фоновый поток, который работает постоянно. И когда в этом потоке происходят некоторые действия мне надо открыть форму, информирующую о выполнении, а затем при завершении этого поддействия - закрыть форму. Но поток продолжает работать постоянно.
 Т.е. как-то надо вызвать форму из этого потока, но я как не пробовал, форма всегда виснет
PM MAIL   Вверх
-Mikle-
Дата 8.5.2009, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

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



Если ты сделаешь через BackgroundWorker, то ты можешь оповещать основной поток о том или ином через метод ReportProgress.
Если без BackgroundWorker, тебе придется заняться синхронизацией с основным потоком самостоятельно.

Приведу пример который был выше, адаптированный под твою задачу.
1. Убери из метода backgroundWorker1_RunWorkerCompleted две строчки закрытия progressForm.
2. Убери из btnStart_Click строчки создания progressForm.
3. Измени содержимое методов backgroundWorker1_DoWork и backgroundWorker1_ProgressChanged на следующее:
Код

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            while (true)
            {
                // выполняем некий код
                System.Threading.Thread.Sleep(5000);

                // *****************************************
                // потребовалось вдруг показать прогресс
                backgroundWorker1.ReportProgress(0, "begin");
                for (int i = 0; i < 100; i++)
                {
                    if (backgroundWorker1.CancellationPending)
                    {
                        e.Cancel = true;
                        break;
                    }

                    System.Threading.Thread.Sleep(100);
                    backgroundWorker1.ReportProgress(i + 1);
                }
                backgroundWorker1.ReportProgress(0, "end");
                // *****************************************
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if ("begin".Equals(e.UserState))
            {
                progressForm = new Form2();
                progressForm.Show(this);
            }
            else if ("end".Equals(e.UserState))
            {
                progressForm.Close();
                progressForm = null;
            }
            else if (progressForm != null && !progressForm.IsDisposed)
                progressForm.progressBar1.Value = e.ProgressPercentage;
        }


Форма с прогрессом будет показываться теперь каждые 5 сек. и выполнять свой прогрес по 10 сек., а затем закрываться и через 5 секс. опять.

Так устроит?


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
artstalker
Дата 8.5.2009, 20:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 5.2.2009

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



Вот это то, что надо! smile  Спасибо

А ещё один вопрос. Как я могу передать информацию из формы в постоянно исполняющийся поток?

Это сообщение отредактировал(а) artstalker - 8.5.2009, 20:05
PM MAIL   Вверх
-Mikle-
Дата 8.5.2009, 20:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

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



Можно передать любой объект в метод RunWorkerAsync и получать его через e.Argument в методе DoWork. Если параметров много, то можно объявить структуру и передавать ее.


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
artstalker
Дата 9.5.2009, 00:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 5.2.2009

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



Мм, надо будет попробовать. Ещё раз спасибо. Это я так сказать теор. почву создаю. Всё руки не дойдут реализовать)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

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


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

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




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


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

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