"简单"问题,在控制台应用程序中,我们如何在主线程中调用System.Timers.Timer
Elapsed事件?
我读过一些关于SyncronizingObject
属性的内容,但目前我还没有成功地尝试实现一个实现ISyncronizeInvoke
接口的类。
编辑(澄清):
我正在尝试模拟一个经典的事件模型。我有一些代码,它使用基于事件的方法来监视一些设备的状态。问题是,有些设备不使用事件发送状态,并要求应用程序轮询数据。
找到的解决方案是使用计时器并轮询设备。如果检测到任何更改,那么我们将引发与现有更改类似的事件。
问题是遗留代码远不是线程安全的,对其进行调整将是一项艰巨的任务。
也许还有更好的方法。
您的主线程首先需要有某种类型的消息循环,以及向该消息循环发送消息的机制。如果你在桌面UI环境中,比如winforms、WPF等,这将是为你创建的,但由于你不是,你需要自己创建一个。
在最初级的层次上,消息循环看起来像这样:
while(!ShouldApplicationExit())
{
var nextMesage = someQueueOfMessages.Dequeue();
nextMessage();
}
当然,您需要公开一些方式,让人们向队列中添加消息,并可能以某种方式指示应用程序应该在某个时刻退出。如果没有项目,队列也应该阻塞,而不是崩溃和烧录。
如果你愿意,你可以自己做这一切。除非它需要特别花哨,否则它并不那么耗时。
其他选项是使用其他东西来创建消息循环,例如Application.Run
,它将在内部有一个循环,看起来有点像我在引擎盖下显示的。
一旦您创建或决定了消息泵的实现,您就可以使用它向泵添加新消息的某种机制。这就是您在ISyncronizeInvoke
实现内部需要做的,调用该机制。
System.Timers.Timer
可以用于触发事件,如果您愿意在系统池的线程上引发事件。
如果您需要在具有更多控制的控制台应用程序中有一个定时回调,您可以CreateThread
您自己的附加线程,有这个WaitForSingleObject
,并在前台任务运行时让事件中断前台任务。
有关类似的讨论,请参阅.Net Timeouts:WaitForSingleObject与Timer。