我的应用程序中有时候需要手动调用我的计时器。
我尝试了以下内容:
int originalInterval = t.Interval;
t.Interval = 0;
t.Interval = originalInterval;
但不一致。
我创建了一个新的计时器,继承自System.Timers.Timer,并公开了一个“Tick”方法 - 但问题是“Elapsed”事件会同步触发。
当我使用新线程实现“Tick”时 - 结果再次不一致。
有没有更好的方法来实现它?
答案 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();
}
在这些示例中,我手动创建了线程。您可以使用该方法,ThreadPool
,Task
或其他任何异步调用代码的方法,无论哪种方法最适合您的上下文。
答案 2 :(得分:0)
通常,您不需要手动触发计时器 - 您始终可以在新线程中运行事件本身。总的来说,这基本上就是计时器的作用,而且由于你想手动启动它,你不需要计时器(用于那个手动调用)。
您没有详细说明“不一致”的含义。以下通常应该有效:
Thread thread = new Thread(myDelegate);
thread.Start();
当然,myDelegate
可以是lambda,以防您需要传递参数:
Thread thread = new Thread(() => myMethod(param1, param2));
thread.Start();