告诉计时器对象以异步方式调用其“Elapsed”事件

时间:2010-08-30 07:32:46

标签: c# asynchronous timer

我的应用程序中有时候需要手动调用我的计时器。

我尝试了以下内容:

int originalInterval = t.Interval;
t.Interval = 0;
t.Interval = originalInterval;

但不一致。

我创建了一个新的计时器,继承自System.Timers.Timer,并公开了一个“Tick”方法 - 但问题是“Elapsed”事件会同步触发。

当我使用新线程实现“Tick”时 - 结果再次不一致。

有没有更好的方法来实现它?

3 个答案:

答案 0 :(得分:4)

我曾经遇到同样的问题,所以我使用AutoResetEvent知道是否成功调用了Elapsed:

/// <summary>
/// Tickable timer, allows you to manually raise a 'Tick' (asynchronously, of course)
/// </summary>
public class TickableTimer : System.Timers.Timer
{
    public new event ElapsedEventHandler Elapsed;

    private System.Threading.AutoResetEvent m_autoResetEvent = new System.Threading.AutoResetEvent(true);

    public TickableTimer()
        : this(100)
    {
    }

    public TickableTimer(double interval)
        : base(interval)
    {
        base.Elapsed += new ElapsedEventHandler(TickableTimer_Elapsed);
    }

    public void Tick()
    {
        new System.Threading.Thread(delegate(object sender)
        {
            Dictionary<string, object> args = new Dictionary<string, object>
            {
                {"signalTime", DateTime.Now},
            };
            TickableTimer_Elapsed(this, Mock.Create<ElapsedEventArgs>(args));
        }).Start();
        this.m_autoResetEvent.WaitOne();
    }

    void TickableTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        m_autoResetEvent.Set();
        if (this.Elapsed != null)
            this.Elapsed(sender, e);
    }
}

答案 1 :(得分:3)

感觉你应该看一下你的设计。通常我会尽量避免让事件处理程序方法包含正在完成的实际工作,但我宁愿让它只是一个触发器,调用一些执行工作的其他方法。这样你就可以从其他任何地方调用其他方法:

private void Timer_Tick(object sender, EventArgs e)
{
    new Thread(MethodThatDoesTheWork).Start();
}

private void MethodThatDoesTheWork()
{
    // actual work goes here
}

现在,您可以从类中的任何其他位置调用MethodThatDoesTheWork(使用单独的线程同步或异步)。

或者,如果MethodThatDoesTheWork 总是是异步调用,则可以在该方法中生成线程:

private void MethodThatDoesTheWork()
{
    new Thread(() =>
    {
         // work code goes here
    }).Start();
}

在这些示例中,我手动创建了线程。您可以使用该方法,ThreadPoolTask或其他任何异步调用代码的方法,无论哪种方法最适合您的上下文。

答案 2 :(得分:0)

通常,您不需要手动触发计时器 - 您始终可以在新线程中运行事件本身。总的来说,这基本上就是计时器的作用,而且由于你想手动启动它,你不需要计时器(用于那个手动调用)。

您没有详细说明“不一致”的含义。以下通常应该有效:

Thread thread = new Thread(myDelegate);
thread.Start();

当然,myDelegate可以是lambda,以防您需要传递参数:

Thread thread = new Thread(() => myMethod(param1, param2));
thread.Start();