Отмена цикла с Thread.Sleep
От: yesenin_toxa Россия yesenin-toxa.livejournal.com
Дата: 30.07.07 14:58
Оценка:
Доброго времени!
Вот есть такое дело:

        private void button1_Click(object sender, EventArgs e)
        {
            do
            {
                    Thread.Sleep(500);
                   
                    foreach (...)
                    {
                        //Здесь двигаем и перерисовываем фигурки
                    }
                    this.pictureBox1.Image = TerrPainter.m_Bitmap;
                    this.Refresh();
            } while (DateTime.Now.Second != 0); //к примеру такое время
        }


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

Подсказали что надо использовать for(!continue). Но как — ума не приложу.
Понимаю, что RTFM, но время очень поджимает.
Не подскажите ли линком или кодом?

P.S. Первый пост, если что не так — приму с пониманием и виной.


31.07.07 12:39: Перенесено модератором из '.NET' — TK
Re: Отмена цикла с Thread.Sleep
От: assm-spb Россия  
Дата: 30.07.07 18:21
Оценка:
Здравствуйте, yesenin_toxa, Вы писали:

_>
_>        private void button1_Click(object sender, EventArgs e)
_>        {
_>            do
_>            {
_>                    Thread.Sleep(500);
                   
_>                    foreach (...)
_>                    {
_>                        //Здесь двигаем и перерисовываем фигурки
_>                    }
_>                    this.pictureBox1.Image = TerrPainter.m_Bitmap;
_>                    this.Refresh();
_>            } while (DateTime.Now.Second != 0); //к примеру такое время
_>        }
_>


_>Но дело в том, что пока минута не кончится закрыть окно, или что то сделать с формой не получается.


Не совсем понятно, что вы собирались сделать этим кодом. Я вижу так: при нажатии какой-то кнопки вызывается Ваш метод button1_Click. Там в течение какого-то периода времени, но не более минуты, постоянно происходит перерисовка каких-то объектов. Например, при входе в метод время 12 час 00 мин 2 сек. В этом случае Ваш цикл будет крутиться 58 сек и остановится когда будет 12 час 01 мин 00 сек. Это как раз минута. Если при входе в метод время 12 час 00 мин 00 сек, то ваш цикл отработает, скорее всего, один раз благодоря do. Если при входе в метод время 12 час 00 мин 59 сек, то цикл будет работать всего 1 сек — до 12 час 01 мин 00 сек.
То есть Вы понимаете, что в течение периода времени от 0,5 до 59 секунд постоянно отрабатывает цикл foreach. Если в течение всего этого периода меняются какие-либо параметры Ваших объектов (фигур), то это что-то типа анимации (зацепился за слово двигаем в комментарии). Для чего Вы вызываете Sleep(500)? Для получения визуального эффекта движения, или для того, чтобы дать другим потокам возможность отработать (как вы думаете), иначе вы не можете двигать форму?
Re: Отмена цикла с Thread.Sleep
От: nerozero  
Дата: 30.07.07 19:13
Оценка:
Здравствуйте, yesenin_toxa, Вы писали:

_>Доброго времени!

_>Вот есть такое дело:

_>
_>        private void button1_Click(object sender, EventArgs e)
_>        {
_>            do
_>            {
_>                    Thread.Sleep(500);
                   
_>                    foreach (...)
_>                    {
_>                        //Здесь двигаем и перерисовываем фигурки
_>                    }
_>                    this.pictureBox1.Image = TerrPainter.m_Bitmap;
_>                    this.Refresh();
_>            } while (DateTime.Now.Second != 0); //к примеру такое время
_>        }
_>


Если я вас правильно понял, в чем я сильно сомневаюсь, то попробуйте так:


private void button1_Click(object sender, EventArgs e)
        {
           Thread t = new Thread(new ThreadStart(delegate()
           {
            do
            {
                    Thread.Sleep(500);
                   
                    foreach (...)
                    {
                        //Здесь двигаем и перерисовываем фигурки
                    }
                    //this.pictureBox1.Image = TerrPainter.m_Bitmap;
                    //Cross thread Invoke
                    this.pictureBox1.Invoke(new MethodInvoker(delegate()
                    {
                        this.pictureBox1.Image = TerrPainter.m_Bitmap;
                        this.Refresh();
                    }));
                    
            } while (DateTime.Now.Second != 0); //к примеру такое время
            
            }));
            
            t.Start();
        }


тоесть создаем новый поток, и все делаем в нем.... а основной поток волен делать все что угодно...
Re[2]: Отмена цикла с Thread.Sleep
От: Аноним  
Дата: 30.07.07 20:50
Оценка:
Здравствуйте, assm-spb, Вы писали:

AS>Не совсем понятно, что вы собирались сделать этим кодом. Я вижу так: при нажатии какой-то кнопки вызывается Ваш метод button1_Click. Там в течение какого-то периода времени, но не более минуты, постоянно происходит перерисовка каких-то объектов. Например, при входе в метод время 12 час 00 мин 2 сек. В этом случае Ваш цикл будет крутиться 58 сек и остановится когда будет 12 час 01 мин 00 сек. Это как раз минута. Если при входе в метод время 12 час 00 мин 00 сек, то ваш цикл отработает, скорее всего, один раз благодоря do. Если при входе в метод время 12 час 00 мин 59 сек, то цикл будет работать всего 1 сек — до 12 час 01 мин 00 сек.

AS>То есть Вы понимаете, что в течение периода времени от 0,5 до 59 секунд постоянно отрабатывает цикл foreach. Если в течение всего этого периода меняются какие-либо параметры Ваших объектов (фигур), то это что-то типа анимации (зацепился за слово двигаем в комментарии). Для чего Вы вызываете Sleep(500)? Для получения визуального эффекта движения, или для того, чтобы дать другим потокам возможность отработать (как вы думаете), иначе вы не можете двигать форму?

Да. Sleep тут нужен для анимации.
Смысл программ -- примитивный Террариум.
Но беда в том, что сделать нужно на максимально примитивном уровне.
Большинство ребят, оставило как есть -- то есть "не трогать пока анимация не кончится".
Я упрямо думаю, что выход есть. Или я безнадежно упрям?
Re[3]: Отмена цикла с Thread.Sleep
От: assm-spb Россия  
Дата: 30.07.07 22:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Да. Sleep тут нужен для анимации.

А>Смысл программ -- примитивный Террариум.
А>Но беда в том, что сделать нужно на максимально примитивном уровне.
А>Большинство ребят, оставило как есть -- то есть "не трогать пока анимация не кончится".
А>Я упрямо думаю, что выход есть. Или я безнадежно упрям?

В кратце, во время работы windows-программы единственное, чем занимается главный поток — это извлекает сообщения из очереди и вызывает соответствующие методы. И вот представьте себе, что очередное сообщение — это нажатие вашей кнопки и вызов метода button1_Click, где в течение минуты происходит отрисовка фигур. В это время остальные сообщения (например о попытке схватить и перетащить форму) попадают в очередь, но не извлекаются главным потоком из нее, так как он занят отрисовкой фигур в методе button1_Click. Естественно, форма, "зависает". Для разрешения этой проблемы есть несколько путей:
1. При нажатии кнопки в методе button1_Click создать второй поток, который и будет рисовать анимацию. Самый правильный, но и самый сложный.
2. При нажатии кнопки создать таймер, в обработчике которого и отрисовывать фигуры, перезапуская таймер каждые 500 мс. Самый оптимальный в вашем случае.
3. Повесить обработчик на событие что-то типа OnIdle. Это функция, которая вызывается в моменты, когда вашей программе нечего делать, так как вы тупо смотрите на ее интерфейс. Там нужно тоже синхронизироваться так, что бы не ранее чем через каждые 500 мс выводить очередное положение фигур. Так что без таймера (но без события) не обойтись. Самый безобидный для интерфейса. Вы рисуете, когда это возможно.
Может и еще есть способы.

Успехов.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.