简体   繁体   English

C#定时器奇怪的行为

[英]c# timer strange behavior

private void aMethod()
    {
        aTimer = new System.Timers.Timer(3000);
        aTimer.Elapsed += new ElapsedEventHandler(OnTimerEvent);
        aTimer.Enabled = true;
        aTimer.Start();
    }

private void button4_Click(object sender, RoutedEventArgs e)
    {
        fileEntries = Directory.GetFiles(@"C:\Users\John\Documents\Visual Studio 2010\Projects\ComeOn\ComeOn\bin\Debug\come");
        aMethod();
        index = 0;
    }

private void OnTimerEvent(Object sender, ElapsedEventArgs e)
    {
            Bitmap LogoImg = new Bitmap(fileEntries[index]);
            LogoImg.MakeTransparent(LogoImg.GetPixel(1, 1));
            this.Dispatcher.Invoke(
                new Action(() => image1.Source = GetBitmapSource(LogoImg)));
            index++;
    }

The length of fileEntries is 3. I created a timer which will start on 3 seconds. fileEntries的长度为3。我创建了一个计时器,该计时器将在3秒后开始。 First it will execute image1.Source = GetBitmapSource(LogoImg)//for fileEntries[0] for 3 seconds, then for fileEntries[1] for 3 seconds and in the end fileEntries[2] for 3 seconds. 首先它将执行image1.Source = GetBitmapSource(LogoImg)//对于fileEntries [0]执行3秒钟,然后对fileEntries [1]执行3秒,最后执行fileEntries [2] 3秒。

But, my program does this: 但是,我的程序这样做:

Start the timer, run fileEntries[0], fileEntries[1] and fileEntries[2] for 0.05 seconds, then wait 3 seconds, then start again. 启动计时器,运行fileEntries [0],fileEntries [1]和fileEntries [2] 0.05秒,然后等待3秒,然后再次启动。 Why is this? 为什么是这样?

How often did you click that button? 您多久点击一次该按钮?

Every time you press the button, a new event handler will be hooked to the timer. 每次您按下按钮时,都会将新的事件处理程序挂接到计时器上。 You never unsubscribe the event handler. 您永远不会取消订阅事件处理程序。

You should either prevent the button from being clicked while you are performing the required work, or you should unsubscribe before subscribing again. 您应该在执行所需的工作时防止单击该按钮,或者应该取消订阅然后再次订阅。


As Hans Passant states in his comment, you should probably also look into using a BackgroundWorker . 正如Hans Passant在评论中指出的那样,您可能还应该考虑使用BackgroundWorker

You shouldn't do 你不应该做

aTimer = new System.Timers.Timer(3000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimerEvent);
aTimer.Enabled = true;
aTimer.Start();

more than once. 不止一次。 Do it in Form_Load event, or in constructor. 在Form_Load事件或构造函数中执行此操作。 in your OnTimerEvent event, prevent your code from being executed when files aren't initialized, for example 在您的OnTimerEvent事件中,例如,防止在文件未初始化时执行代码

int index = -1;
private void OnTimerEvent(Object sender, ElapsedEventArgs e)

        {
             if(index != -1)
             {
                Bitmap LogoImg = new Bitmap(fileEntries[index]);
                LogoImg.MakeTransparent(LogoImg.GetPixel(1, 1));
                this.Dispatcher.Invoke(
                    new Action(() => image1.Source = GetBitmapSource(LogoImg)));
                index++;
             }
             if (index == 3) // when all 3 were loaded, reset index. You can also stop the timer if you won't be loading files the second time
             {
                index=-1;
             }
        }

Or you should unsuscribe before you add new event handler. 或者,您应在添加新的事件处理程序之前取消订阅。 But keeping track of how many event handlers are added to an event is tricky (or I should say I havn't found a way to do it yet). 但是,跟踪添加到事件中的事件处理程序的数量非常棘手(或者我应该说我还没有找到一种方法来做到这一点)。

As @Steven Jeuris said, when an event handler is added to an event, it is literaly ADDED, to event handlers LIST. 正如@Steven Jeuris所说,将事件处理程序添加到事件中时,实际上是将其添加到事件处理程序LIST中。 So every time when your timer elapses every event handler on the list is executed, which means if there are 3 event handlers added (as in your case) the event handler method will execute 3 times. 因此,每当您的计时器经过时,就会执行列表中的每个事件处理程序,这意味着,如果添加了3个事件处理程序(如您的情况),则事件处理程序方法将执行3次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM