Таймер для запуска события WPF

У меня есть проект здесь, и по умолчанию установлено, что действия происходят по событию MouseEnter. Я имею в виду, что открытие окна, закрытие, возврат, что угодно, происходит только по событию MouseEnter.

Меня попросили запустить событие только через 3 секунды. Это означает, что пользователь поместит мышь на элемент управления, и только через 3 секунды событие должно произойти для всех элементов управления в окне.

Итак, я подумал о глобальном таймере или чем-то подобном, который будет возвращать false до тех пор, пока таймер не достигнет 3... Я думаю, что так...

Боже, кто-нибудь знает, как я могу сделать такую ​​​​вещь?

Спасибо!!


person Armando Freire    schedule 09.09.2012    source источник
comment
Разве ты не можешь просто поспать 3 секунды в событии MouseEnter?   -  person paparazzo    schedule 09.09.2012
comment
Сон в течение 3 секунд в событии MouseEnter заблокирует пользовательский интерфейс на 3 секунды.   -  person Wonko the Sane    schedule 01.11.2012


Ответы (2)


Вы можете определить класс, который будет предоставлять метод DelayedExecute, который получает действие для выполнения и создает таймеры по мере необходимости для отложенного выполнения. Это будет выглядеть примерно так:

public static class DelayedExecutionService
{
    // We keep a static list of timers because if we only declare the timers
    // in the scope of the method, they might be garbage collected prematurely.
    private static IList<DispatcherTimer> timers = new List<DispatcherTimer>();

    public static void DelayedExecute(Action action, int delay = 3)
    {
        var dispatcherTimer = new System.Windows.Threading.DispatcherTimer();

        // Add the timer to the list to avoid it being garbage collected
        // after we exit the scope of the method.
        timers.Add(dispatcherTimer);

        EventHandler handler = null;
        handler = (sender, e) =>
        {
            // Stop the timer so it won't keep executing every X seconds
            // and also avoid keeping the handler in memory.
            dispatcherTimer.Tick -= handler;
            dispatcherTimer.Stop();

            // The timer is no longer used and shouldn't be kept in memory.
            timers.Remove(dispatcherTimer);

            // Perform the action.
            action();
        };

        dispatcherTimer.Tick += handler;
        dispatcherTimer.Interval = TimeSpan.FromSeconds(delay);
        dispatcherTimer.Start();
    }
}

Затем вы можете назвать это так:

DelayedExecutionService.DelayedExecute(() => MessageBox.Show("Hello!"));

or

DelayedExecutionService.DelayedExecute(() => 
{
    DoSomething();
    DoSomethingElse();
});
person Adi Lester    schedule 09.09.2012
comment
Ух ты! Отличное решение, сэр!! Это сработало отлично! Я просто собираюсь подумать о визуальной обратной связи, например, о растущем круге вокруг курсора или о чем-то подобном!! Большое спасибо! - person Armando Freire; 09.09.2012
comment
@ArmandoFreire Рад слышать. Обратите внимание, что я изменил код, чтобы избежать возможной утечки памяти. - person Adi Lester; 09.09.2012
comment
Конечно, @AdiLester, я тоже только что обновил свой! Код сэкономил кучу времени! Большое спасибо! - person Armando Freire; 09.09.2012
comment
Эй, @Adi, как мне добавить более одного метода к этому событию? Я имею в виду, что я пытаюсь запустить два метода (например, вызов двух окон сообщений), но это не работает. Должен ли я вызывать эту функцию дважды? - person Armando Freire; 15.09.2012
comment
@ArmandoFreire Делегат, который вы передаете, может выполнять несколько операторов. Я обновил свой ответ, чтобы продемонстрировать это. - person Adi Lester; 15.09.2012
comment
Есть ли способ сделать то же самое в шаблоне XAML? Я пытаюсь сделать анимацию при нажатии кнопки, но я не хочу, чтобы событие CLick запускалось до завершения анимации. - person Stefan Vasiljevic; 19.07.2014
comment
@StefanVasiljevic В этом случае вы можете зарегистрироваться в событии Completed раскадровки и выполнить там свою логику. - person Adi Lester; 19.07.2014
comment
@СтефанВасильевич Да. Погуглите событие Completed — уверен, вы найдете множество примеров. - person Adi Lester; 19.07.2014
comment
не могли бы мне помочь, я пытаюсь реализовать этот код, чтобы отложить запуск события изменения текста, и я немного потерялся... - person Little Programmer; 19.07.2016
comment
Я хочу отложить даже от стрельбы каждый раз, когда он вызывается во время одного прогона на 3 секунды. - person Little Programmer; 19.07.2016
comment
@LittleProgrammer Вероятно, вы ищете отложенную привязку: jonathanantoine.com/2011/09/21/ - person Adi Lester; 19.07.2016

Я просто хотел добавить более простое решение:

public static void DelayedExecute(Action action, int delay = 3000)
{
    Task.Factory.StartNew(() => 
    {
        Thread.Sleep(delay);
        action();
    }
}

Затем используйте его так же, как в этом другом ответе

person Louis Kottmann    schedule 15.09.2012
comment
Это действительно проще, но я думаю, что Sleep следует избегать, когда это возможно. - person Adi Lester; 15.09.2012
comment
@AdiLester, не могли бы вы прокомментировать, почему? - person Louis Kottmann; 15.09.2012
comment
В этой статье указано несколько причин: .aspx" rel="nofollow noreferrer">msmvps.com/blogs/peterritchie/archive/2007/04/26/ - person Adi Lester; 15.09.2012