Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Реализация задержки с помощью таймера


Автор: AGENTxXx 26.1.2010, 22:41
Всем привет! Вот такая задача: нужно чтобы курсор мыши двигался с задержкой (ну я зам указываю куда нужно курсор переместить). Так вот, Sleep() не подходит потому что во время движений курсора нужен доступ к форме (ну например курсор не правильно пошел и нужно выйти из проги). Т.е. в итоге должно получиться: курсор бегает с задержкой, а с формой можно работать тем временем. Проблема в том что у меня не получилось это реализовать с таймером, и так и сяк.... он бегает но без задержек((( пробывал в другой поток занести движение курсора, но выдовалась ошибка, так как первый поток проходил нормально, ну который создался новый, а 2-й раз когда запрашивалось туда обращение уже выходила ошибка, ругалось на то что не правильное обращение или поток уже существует... А алгоритм у меня с потоками был такой: вызываю вот этот дополнительный поток, а в нем просто sleep() делаю и все. Но думаю что можно гораздо проще. Вот код:
Код

private void timer1_Tick(object sender, EventArgs e)
        {
            if (i<=r-2) //проверка, есть ли еще координаты 
            {
                f.X = Convert.ToInt32(strarray[i]);
                f.Y = Convert.ToInt32(strarray[i+1]);
                Cursor.Position = f;
                Thread.Sleep(Convert.ToInt32(strarray[i + 2])*10); //замораживаем курсор...ну и как видно саму прогу(( 
                //strarray[i + 2]*10 - тут уазанно количество миллисекунд
                i += 4;
            }
            else
            {
                timer1.Enabled = false; // ну когда уже вводить не че, то останавливаем таймер
            }




Так же могу привести мою модификацию, где пробывал через поток:
Код

         Thread t = new Thread(new ThreadStart(ThreadProc));

        private static void ThreadProc()
       {
            Thread.Sleep(Convert.ToInt32(strarray[i + 2]) * 10);
            t.Suspend(); //нельзя указать в статической функции, а иначе не знаю как реализовать останов данного потока
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (i<=r-2)
            {
                f.X = Convert.ToInt32(strarray[i]);
                f.Y = Convert.ToInt32(strarray[i+1]);
                Cursor.Position = f;
                if (t.IsAlive) //проверка активный ли поток
                {
                    t.Resume();
                }
                else
                {
                    t.Start();   
                }
                i += 4;
            }
            else
            {
                timer1.Enabled = false;
            }
            
        }


Пробывал еще с таймером но тоже дохлый номер, думаю пользы приводить пример нет, но если надо, то приведу. А так, прошу вот помощи у знающих людей. Пожалуйста, помогиче чем можете! 

Автор: Sfate 27.1.2010, 00:51
самый простой способ выполнять метод периодически – использовать таймер, например класс Timer из пространства имен System.Threading... этот таймер использует пул потоков, допуская создание множества таймеров без накладных расходов в виде такого же количества потоков... Timer – довольно простой класс с конструктором и парой методов...

Код
public sealed class Timer : MarshalByRefObject, IDisposable
{
  public Timer(TimerCallback tick, object state, 1st, subsequent);
  public bool Change(1st, subsequent);  // Для изменения периода
  public void Dispose();                // Для удаления
}
// 1st = время до первого срабатывания в миллисекундах или как TimeSpan
// subsequent = следующие интервалы в миллисекундах или как TimeSpan 
// (используйте Timeout.Infinite для одноразового срабатывания)


в следующем примере таймер вызывает метод Tick, который печатает "tick..." по истечении 5 секунд и далее каждую секунду, пока пользователь не нажмет Enter:

Код

using System;
using System.Threading;
 
class Program 
{
  static void Main() 
  {
    Timer tmr = new Timer(Tick, "tick...", 5000, 1000);
    Console.ReadLine();
    tmr.Dispose();           // Остановка таймера
  }

  static void Tick(object data) 
  {
    // Этот код выполняется на потоке из пула
    Console.WriteLine(data); // Печать: "tick..."
  }
}

Автор: AGENTxXx 27.1.2010, 02:02
Спсибо за совет! Вещь дельная, согласено, но я не понял как она действует млин. Вот, пишу например:
Код

 private void button5_Click(object sender, EventArgs e)
        {
System.Threading.Timer tmr = new System.Threading.Timer(Ui, 0, 1000, 0);
}
public void Ui(object data)
        {
            richTextBox1.Text = richTextBox1.Text + "1";
        }

Тут меня все устраивает. Через секунду записал 1 единицу.
Написал так:
Код

 private void button5_Click(object sender, EventArgs e)
        {
int u=10;
System.Threading.Timer tmr = new System.Threading.Timer(Ui, 0, 1000, 0);
tmr.Change(u, 50);
}
public void Ui(object data)
        {
            richTextBox1.Text = richTextBox1.Text + "1";
        }

По идее здесь должен быть бесконечный цикл где каждые 50 миллисекунд должна дописываться 1, но касяк в том, что все само собой почему то останавливается, и самое что интересное: количество единиц выдает по разному. ПОЧЕМУ ПОРАЗНОМУ ТО? Эт вообще какое то чудо.


Короче хотелось бы узнать ответ.. На счет своего способа. Решил сделать так: просто менять у моего таймера интервал на нужное число, и в общем все как надо заработало. Все же если конечно твой способ Sfate более экономен по соотношению к процессорному времени то хотелось бы все же реализовать по твоему. Только думаю что скорей всего значение их будет равными. Джу ответа на не понятную для меня мистику)

Автор: Sfate 28.1.2010, 22:53
ну... может он не сотанавливается, а виснет? необходимо аккуратно вешать таймеры с циклами... и обязательно где-то останавливать иначе можно повесить свою железку...
вообще таймер, очень странная штука и к примеру если задать шаг тика в 1с, то он может сработать и при значении 0,8с, так что при 10с работы мы можем получить не число 10, а почти 13... также таймер может сгрешить и в большую сторону... но эт редко... и погрешность у него всегда разная)

мой код может и будет более продуктивен... у меня то прост ступор есть (остановка по нажатию на кнопку)...
в принципе нагрузка будет приблизительно одинаковой... и для нынешних процов разница не существена...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)