我想构建一个Windows服务,它应该在不同的时间执行不同的方法。它根本不是准确性。 我使用system.timers.timer,并使用计数器调节在Eventhandler方法中执行的不同方法。多才那就好了。
所有方法都在访问COM端口,因此必须一次只向一个方法授予acceess-rights权限。但由于这些方法可能需要一些时间才能完成,因此计时器可能会再次打勾并希望在COM端口仍被占用时执行另一种方法。在这种情况下,事件可以而且应该被解雇。
简化为一个方法,我的elapsedEventHandler方法看起来像下面这样(try-catch和这里排除的不同方法)
注意:虽然这在我的Win7 x64上完美运行,但是只要要执行的方法需要很长时间,它就会在安装了相同软件的Win7 x86机器上挣扎。计时器不会再打勾,不会抛出异常。没有!我现在的问题是:我是否正在使用访问控制和计时器权限,以便我可以专注于其他事情?我只是不熟悉计时器,特别是线程
private static int m_synchPoint=0;
private System.Timers.Timer timerForData = null;
public MyNewService()
{
timerForData = new System.Timers.Timer();
timerForData.Interval = 3000;
timerForData.Elapsed += new ElapsedEventHandler(Timer_tick);
}
//Initialize all the timers, and start them
protected override void OnStart(string[] args)
{
timerForData.AutoReset = true;
timerForData.Enabled = true;
timerForData.Start();
}
//Event-handled method
private void Timer_tick(object sender, System.Timers.ElapsedEventArgs e)
{
////safe to perform event - no other thread is running the event?
if (System.Threading.Interlocked.CompareExchange(ref m_synchPoint, 1, 0) == 0)
{
//via different else-ifs basically always this is happening here, except switching aMethod,bMethod...
processedevent++;
Thread workerThread = new Thread(aMethod);
workerThread.Start();
workerThread.Join();
m_synchPoint=0;
}
else
{
//Just dismiss the event
skippedevent++;
}
}
非常感谢您提前! 非常感谢任何帮助!
答案 0 :(得分:4)
我建议使用System.Threading.Timer
来实现此功能。您可以在执行时禁用计时器,处理数据,然后重新启用计时器。
编辑:
我认为使用System.Threading.Timer
更有意义,因为没有理由需要将计时器放在设计图面上,这几乎是使用System.Timers.Timer
的唯一原因。我真的希望MS无论如何都要移除它,它包装System.Threading.Timer
并不是一开始就难以使用。
是的,你冒着重入问题的风险,这就是我指定将超时更改为Timeout.Infinite
的原因。如果使用Timeout.Infinite
构建计时器,则不会出现此重新入侵问题。
public class MyClass
{
private System.Threading.Timer _MyTimer;
public MyClass()
{
_MyTimer = new Timer(OnElapsed, null, 0, Timeout.Infinite);
}
public void OnElapsed(object state)
{
_MyTimer.Change(Timeout.Infinite, Timeout.Infinite);
Console.WriteLine("I'm working");
_MyTimer.Change(1000, Timeout.Infinite);
}
}
答案 1 :(得分:2)
你可以试试这个:
当计时器触发时,禁用计时器。
任务完成后,重新启用计时器......可能在Finally子句中。
答案 2 :(得分:2)
如果您只想跳过方法调用而前一个方法没有完成,只需在调用方法之前使用Monitor.TryEnter(lockObject)
。
编辑: 这是一个例子 -
public class OneCallAtATimeClass
{
private object syncObject;
public TimerExample()
{
syncObject = new object();
}
public void CalledFromTimer()
{
if (Monitor.TryEnter(syncObject);)
{
try
{
InternalImplementation();
}
finally
{
Monitor.Exit(syncObject);
}
}
}
private void InternalImplementation()
{
//Do some logic here
}
}
答案 3 :(得分:2)
您正确使用CompareExchange
在进行初步检查时测试并设置m_synchPoint
字段。您错误使用直接分配将方法结束时的值重置为0。您应该使用Interlocked.Exchange来将值重置为0.作为旁注,您还应该将m_synchPoint更改为实例字段 - 它不应该是静态的。