只有前一个完成引发事件 [英] Only raise an event if the previous one was completed

查看:150
本文介绍了只有前一个完成引发事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的应用程序中使用 System.Timers.Timer 。每一秒我运行一个函数,做一些工作。问题是,这个功能可以为一些小的时间块(读取然后从磁盘处理大量文件)。我想开始仅当它以前的执行实例已完成该功能。我以为我可以用互斥实现这一点:

I'm using a System.Timers.Timer in my application. Every second I run a function which does some job. The thing is, this function can block for some little time (it reads then processes a large file from disk). I want to start that function only if its previous "execution instance" has completed. I thought I could achieve this with a Mutex:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static Mutex TimerMut = new Mutex(false);
        public static void Main()
        {

            Thread TT = new Thread(new ThreadStart(delegate()
            {
                System.Timers.Timer oTimer = new System.Timers.Timer();
                oTimer.Elapsed += new ElapsedEventHandler(Handler);

                oTimer.Interval = 1000;
                oTimer.Enabled = true;
            }));

            TT.Start();

            Console.Read();
        }

        private static void Handler(object oSource,
            ElapsedEventArgs oElapsedEventArgs)
        {
            TimerMut.WaitOne();
            Console.WriteLine("foo");
            Thread.Sleep(500);         //simulate some work
            Console.WriteLine("bar");
            TimerMut.ReleaseMutex();
        }
    }
}

这是不行的, FOOS仍然会出现每秒。我怎样才能做到这一点。

That doesn't work, "foos" still appear every second. How can I achieve this?

编辑:你说得对,这是没有意义的开始一个新的线程来处理这个问题。我以为只有 System.Threading.Timer 在一个单独的线程启动。

You're right, it makes no sense to start a new thread to handle this. I thought only System.Threading.Timer is launched in a separate thread.

推荐答案

我所知道的最简单的方法做这样的事情:

Easiest way I know of to do this kind of thing:

internal static volatile bool isRunning;

public static void Main()
    {
        Thread TT = new Thread(new ThreadStart(delegate()
            {
                System.Timers.Timer oTimer = new System.Timers.Timer();
                oTimer.Elapsed += new ElapsedEventHandler(Handler);

                oTimer.Interval = 1000;
                oTimer.Enabled = true;                 
            }));

        TT.Start();
    }

    private void Handler(object oSource,
        ElapsedEventArgs oElapsedEventArgs)
    {
        if(isRunning) return;

        isRunning = true;

        try
        {
           Console.WriteLine("foo");
           Thread.Sleep(500);         //simulate some work
           Console.WriteLine("bar");
        }
        finally { isRunning = false; }            
    }

的处理程序仍然运行,但它的第一件事就是确保另一个处理程序没有运行,如果有,它会立即停止。

The handler still runs, but the very first thing it does is make sure that another handler isn't running, and if one is, it stops immediately.

有关执行处理更加迅速(如3-4次),定时器,这有可能性种族;两个线程可以继续过去的后卫条款其中一个设置位之前。

For timers executing handlers more quickly (like 3-4 times a second), this has the possibility to race; two threads could proceed past the guard clause before one of them sets the bit. You can avoid this with a couple of lock statements, similar to a Mutex or Monitor:

    static object syncObj = new object();

    private void Handler(object oSource,
        ElapsedEventArgs oElapsedEventArgs)
    {
        lock(syncObj)
        {
           if(isRunning) return;            
           isRunning = true;
        }

        try
        {
           Console.WriteLine("foo");
           Thread.Sleep(500);         //simulate some work
           Console.WriteLine("bar");
        }
        finally { lock(syncObj) { isRunning = false; } }            
    }

这将确保只有一个线程可以永远被检查或修改isRunning ,并作为isRunning标记挥发,CLR将不缓存它的价值,因为每个线程的性能状态的一部分;每个线程都有看在完全相同的内存位置来检查或更改数值。

This will ensure that only one thread can ever be examining or modifying isRunning, and as isRunning is marked volatile, the CLR won't cache its value as part of each thread's state for performance; each thread has to look at exactly the same memory location to examine or change the value.

这篇关于只有前一个完成引发事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆