c# - 在 Windows 服务中从事件处理程序启动计时器
问题描述
我有一个内置于 vb.net 的 Windows 服务,它接收来自 MQTT 服务器的消息。消息通过附加到事件处理程序的 Sub 接收和处理。工作正常。
此外,我需要启动一个定时器,它将并行发送一个信号到“蜂鸣器”,蜂鸣器,停止,蜂鸣器......这个子例程本身就可以正常工作。
在 Windows 服务和 Windows 窗体中,它都不能完美运行。Timer 必须由链接到 Event Handler 的 Sub 启用(一旦收到并处理 MQTT 消息,启动计时器)。定时器通常设置为 1000ms。子例程在 Timer 到达 1000ms 之前完成,并且永远不会触发 Tick 事件。
在 Windows 窗体中,我使用 Me.Invoke 解决了这个问题。Timer's Tick 事件按预期触发。但是 Windows 服务中不存在“me.invoke”。我不知道如何继续触发 Tick 事件。
在 Windows 窗体中,我能够创建一个委托并使用 Me.Invoke 调用 RefreshMqttScreen ...
所以问题是:一旦 MqttMessageReceived 子程序完成运行,如何让计时器继续运行?
如果 VB 不能满足我的需求,我可以使用 C#...
谢谢
AddHandler _mqttClient.ApplicationMessageReceived, AddressOf MqttMessageReceived
Public Sub MqttMessageReceived(ByVal sender As Object, ByVal e As MqttApplicationMessageReceivedEventArgs)
RefreshMQTTScreen(some parameters here)
End Sub
Private Sub RefreshMQTTScreen(....)
indexBuzzer = 1
TimerBuzzer.Interval = buzzer.intDuree
TimerBuzzer.Enabled = True
End Sub
Private Sub TimerBuzzer_Tick(sender As Object, e As EventArgs) Handles TimerBuzzer.Tick
TimerBuzzer.Enabled = False
indexBuzzer += 1
If collBuzzerActif.Count >= indexBuzzer Then
Dim buzzer As Derby.ClsBuzzer
buzzer = collBuzzerActif(indexBuzzer)
If buzzer.boolOn And buzzer.intDuree > 0 Then
ChangerStatutDataLogger(True)
If collBuzzerActif.Count >= indexBuzzer + 1 Then
TimerBuzzer.Interval = buzzer.intDuree
TimerBuzzer.Enabled = True
End If
Else
ChangerStatutDataLogger(False)
If collBuzzerActif.Count >= indexBuzzer + 1 Then
TimerBuzzer.Interval = buzzer.intDuree
TimerBuzzer.Enabled = True
End If
End If
End If
End Sub
解决方案
您可以使用任务和一些 ManualResetEvent,而不是使用计时器。当您的服务开始执行此 ONCE 时,
_TimerBuzzerTask = Task.Run(Sub() TimerBuzzer_Tick())
然后进行这些更改
Private Sub RefreshMQTTScreen(....)
indexBuzzer = 1
TimerBuzzerInterval = buzzer.intDuree
_TimerBuzzer_Enabled.Set()
End Sub
Private _TimerBuzzerTask As Task
Private _TimerBuzzer_Enabled As New Threading.ManualResetEvent(False)
Private _TimerBuzzer As New Threading.ManualResetEvent(False) '_TimerBuzzer.Set to end task
Private TimerBuzzerInterval As Integer = 1000
Private Sub TimerBuzzer_Tick()
Do
_TimerBuzzer_Enabled.WaitOne() 'to enable _TimerBuzzer_Enabled.Set()
_TimerBuzzer_Enabled.Reset()
If collBuzzerActif.Count >= indexBuzzer Then
Dim buzzer As Derby.ClsBuzzer
buzzer = collBuzzerActif(indexBuzzer)
If buzzer.boolOn AndAlso buzzer.intDuree > 0 Then
ChangerStatutDataLogger(True)
If collBuzzerActif.Count >= indexBuzzer + 1 Then
TimerBuzzerInterval = buzzer.intDuree
_TimerBuzzer_Enabled.Set()
End If
Else
ChangerStatutDataLogger(False)
If collBuzzerActif.Count >= indexBuzzer + 1 Then
TimerBuzzerInterval = buzzer.intDuree
_TimerBuzzer_Enabled.Set()
End If
End If
End If
Loop While _TimerBuzzer.WaitOne(TimerBuzzerInterval) 'ticks every second
End Sub
如果您的服务停止执行此操作,
_TimerBuzzer.Set
由于显而易见的原因,我无法对此进行测试。
推荐阅读
- javascript - 使用 JavaScript:当我编辑特定的 html 表格行时使用模式类。如何在下拉列表中选择当前值?
- python - Python ldap 模块是否支持 LDAP 通道绑定和 LDAP 签名
- openpyxl - 使用 openpyxl 的空格分隔值
- ios - 从命令行在项目中查找 XCTest 目标
- google-cloud-platform - 从 BigQuery 连接数据集后,Google Data Studio 图表中出现“无数据”消息?
- python - 我想用 Pygame 做一个游戏。但是我的箭不能从正确的位置射出
- scala - 在 Apache Flink 中使用 Dropwizard 直方图度量时违反加载程序约束
- android - NavController 在设备旋转后没有当前导航节点
- javascript - 如果包含文本,jQuery 对多个 DIV 进行排序
- c# - 在 AX 2012 r2 中出现类似“Testing1”的错误不是 AxdEnum_XMLDocPurpose 的有效值