简体   繁体   English

c#-主线程上的System.Timers.Timer经过事件

[英]c# - System.Timers.Timer Elapsed event on main thread

"Simple" question, in a console application, how can we make a System.Timers.Timer Elapsed event be called in the main thread? “简单”问题,在控制台应用程序中,我们如何在主线程中调用System.Timers.Timer Elapsed事件?

I've read something about the SyncronizingObject property but, currently I had no sucess in trying to implement a class which implements ISyncronizeInvoke interface. 我已经阅读了有关SyncronizingObject属性的内容,但是,目前我在尝试实现实现ISyncronizeInvoke接口的类方面没有任何成功。

EDIT (for clarification): 编辑 (为澄清):

I'm trying to simulate a classic event model. 我正在尝试模拟经典事件模型。 I have some code which watches for the state of some devices using an event based approach. 我有一些代码使用基于事件的方法来监视某些设备的状态。 The problem is that some of the devices don't send their statuses using events and require the application to poll for the data. 问题在于某些设备不使用事件发送其状态,而是要求应用程序轮询数据。

The solution found was to use a timer and poll the devices. 找到的解决方案是使用计时器并轮询设备。 If any change was detected, then we would raise a similar event of the existing ones. 如果检测到任何变化,那么我们将引发与现有变化类似的事件。

The problem is that the legacy code is far from thread safe and adapting it would be quite a quest. 问题在于,遗留代码远非线程安全的,对其进行调整将是一个艰巨的任务。

Maybe there's a better approach. 也许有更好的方法。

Your main thread needs to first have a message loop of some sort, and a mechanism of sending messages to that message loop. 您的主线程首先需要具有某种消息循环,以及将消息发送到该消息循环的机制。 If you were in a desktop UI environment such as winforms, WPF, etc., this would be created for you, but since you're not, you need to create one yourself. 如果您在桌面UI环境(例如winforms,WPF等)中,则将为您创建该环境,但由于并非如此,因此您需要自己创建一个。

A message loop, at it's most primative level, looks something like this: 在最原始的级别上,消息循环看起来像这样:

while(!ShouldApplicationExit())
{
    var nextMesage = someQueueOfMessages.Dequeue();
    nextMessage();
}

Then of course you need to expose some way for people to add messages to that queue, and potentially some way of indicating that the application should exit at some point. 然后,当然,您需要公开一些方法供人们将消息添加到该队列中,还可能需要某种方式来指示应用程序应在某个时刻退出。 Your queue should also block if there are no items, rather than crashing and burning. 如果没有项目,您的队列也应该阻塞,而不是崩溃和燃烧。

You could do all of this yourself if you wanted. 如果需要,您可以自己完成所有这些操作。 Unless it needs to be particularly fancy, it's not all that time consuming. 除非需要特别花哨,否则并不需要所有的时间。

Other options would be to use something else to create the message loop, such as Application.Run , which will internally have a loop that looks kinda-sorta like what I showed, under the hood. 其他选择是使用其他东西来创建消息循环,例如Application.Run ,它将在内部具有一个类似于我在后台显示的循环。

Once you have created, or decided upon, your implementation of a message pump, you get with it some mechanism of adding a new message to the pump. 一旦创建或决定了消息泵的实现,您就会获得一些向泵添加新消息的机制。 That's what you need to do inside of your ISyncronizeInvoke implementation, call out to that mechanism. 那就是您需要在ISyncronizeInvoke实现内部执行的操作,并调出该机制。

System.Timers.Timer can be used to trigger events if you are happy to have the event raised on a thread from the system pool. 如果您愿意在系统池的线程上引发事件,则可以使用System.Timers.Timer触发事件。

If you need to have a timed callback in a console application with more control, you can CreateThread your own additional thread, have this WaitForSingleObject and have the event interrupt the foreground task while it is running. 如果你需要有更多的控制控制台应用程序定时回调,你可以CreateThread自己额外的线程,有这样的WaitForSingleObject和有事件中断前台任务在运行时。

See .Net Timeouts: WaitForSingleObject vs Timer for a similar discussion. 有关类似的讨论,请参见.Net超时:WaitForSingleObject与计时器

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM