C# 识别不同的计时器运行(System.Timers.timer)

C# 识别不同的计时器运行(System.Timers.timer),c#,.net,timer,C#,.net,Timer,所以我有一个计时器,它每秒钟运行一次。大多数情况下,运行只需几毫秒,但有时一次计时器运行的执行时间超过1秒。 这本身不是问题,因为c#处理将不同的运行放在不同(或相同)的线程中等 但是,如果我想识别某个方法是通过哪个运行调用的,当同时执行两个运行时,该怎么办? 我希望在控制台中有如下输出: Run 1: Method "GetThisStuff" called Run 1: Method "GetOtherStuff" called Run 2: Method "GetThisStuff" ca

所以我有一个计时器,它每秒钟运行一次。大多数情况下,运行只需几毫秒,但有时一次计时器运行的执行时间超过1秒。 这本身不是问题,因为c#处理将不同的运行放在不同(或相同)的线程中等

但是,如果我想识别某个方法是通过哪个运行调用的,当同时执行两个运行时,该怎么办? 我希望在控制台中有如下输出:

Run 1: Method "GetThisStuff" called
Run 1: Method "GetOtherStuff" called
Run 2: Method "GetThisStuff" called
Run 1: Method "GetFinalStuff" called
Run 2: Method "GetOtherStuff" called
Run 2: Method "GetFinalStuff" called
如果我有一个定时器方法

public static void timer_Elapsed(object sender, ElapsedEventArgs e)  {
     GetMainStuff();
     GetMoreMainStuff();

 }
以及一些虚拟方法:

public void GetMainStuff()
{
   GetThisStuff();
   GetOtherStuff();
}

public void GetMoreMainStuff()
{
   GetFinalStuff();
}
我知道有

ElapsedEventArgs.SignalTime
但我不想通过我的应用程序的每个方法(向下几个“级别”)都将其作为参数

我也知道,不是每一次新的运行都会有一个新的线程

如果我有一个静态时间,它将在每次运行时被覆盖。


有什么想法吗?

由于
System.Timers.Timer
未密封,您可以对其进行扩展以添加计数器属性:

public class TimerWithRunCounter : System.Timers.Timer
{
    public int Counter { get; set; }

    public TimerWithRunCounter(int counter, double interval) : base(interval)
    {
        Counter = counter;
    }
}
在计时器回调中,将
sender
转换为
TimerWithRunCounter
,然后访问并递增计数器:

public static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    var timer = (TimerWithRunCounter)sender;
    lock (lockObject)
    {
        Console.WriteLine("Run {0}", timer.Counter);
        timer.Counter++;
    }
}
用法示例:

var timer = new TimerWithRunCounter(0, 1000);

您是否需要方法本身来了解上下文?或者您只需要在事件处理程序中知道吗

实现这一点的最简单方法是使用事件处理程序在同一类中维护计数器:

private static int _timerCounter;

public static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    int counter = Interlocked.Increment(ref _timerCounter);

    GetMainStuff();
    GetMoreMainStuff();
}
如果每个被调用的方法都需要知道该值,那么您当然可以传递该值:

public static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    int counter = Interlocked.Increment(ref _timerCounter);

    GetMainStuff(counter);
    GetMoreMainStuff(counter);
}
如果您有一个深层调用链,希望在整个上下文中广泛了解计数器,那么您可以继续上述模式,将值向下传递到每个被调用的方法中,或者创建一个“调用上下文”类,将这些方法的代码以及当前计数器的值放入其中:

class TimerContext
{
    private readonly int _timerCount;
    public int TimerCount { get { return _timerCount; } }

    public TimerContext(int timerCount)
    {
        _timerCount = timerCount;
    }

    public void GetMainStuff()
    {
        GetThisStuff();
        GetOtherStuff();
    }

    public void GetMoreMainStuff()
    {
        GetFinalStuff();
    }

    // etc.
}

public static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    TimerContext context = new TimerContext(Interlocked.Increment(ref _timerCounter));

    context.GetMainStuff();
    context.GetMoreMainStuff();
}
这样,作为
TimerContext
类的成员,您调用的每个方法都可以访问计数器


这些只是你可以采取的几种不同的方法。当然,还有其他选项,但希望上面的内容能让您了解这些选项的工作原理(它们都是主题的变体)。

您的断言是错误的,这总是一个问题。只需将AutoReset属性设置为false,并在事件处理程序的末尾调用Start()。我知道多线程通常存在(很多)问题,但这目前并没有给我带来任何问题,这可能就是我的意思。;)但我的问题仍然是,当不同的运行及时重叠时,如何识别它们,而不是让这些运行在彼此之后运行。使用“调用上下文”类的想法很好,因为我有一个很深的调用链,将此参数放在400个左右的方法中是不好的。。。但这仍然是一个问题…,因为我的已用事件处理程序中的所有方法都已经有了可感知的类,所以将所有这些放在上下文类中只会破坏我整洁定义的类和方法。我只是以虚拟方法为例。有什么想法吗?好吧,我想我可以让我所有的类都继承上下文类。。hmmmmI不鼓励仅仅为了共享某些特定数据而继承类。如果你不知道为什么要买柜台,就很难给出具体的建议。也就是说,你说有重叠的计时器处理是可以的,那么为什么确切的顺序很重要呢?如果它是重要的,而不是计数器,您可以考虑通过在事件处理程序中使用锁来进行序列化。最后,请注意,调用上下文的要点是允许每个方法访问计数器。你真的有400种方法需要知道计数器的值吗?