Вероятно, лучшим решением этого является полное избавление от DispatcherTimer и выполнение этого с помощью простых потоков.
Сначала создайте класс для хранения одного рабочего пакета события - я добавил способ передачи значения задержки здесь, но вы можете опустить его, если он не соответствует вашим потребностям. Это простая процедура, которая задерживает поток для задержки, а затем вызывает новое событие для вас. Если вам нужна точность, вы можете реализовать задержку с помощью секундомера или чего-то еще:
Public Class DelayThread
' Task information
Private _ID As Integer
Private _delay As Integer
Event onDelayUp(ByVal ID As Integer)
' Constructor
Public Sub New(ByVal myID As Integer, ByVal myDelay As Integer)
_ID = myID
_delay = myDelay
End Sub
Public Sub DelayProc()
System.Threading.Thread.Sleep(_delay)
RaiseEvent onDelayUp(_ID)
End Sub
End Class
Теперь ваше устройство будет запускать события, обработанные здесь:
Public Sub SomeEventFromExtDevice(ByVal ID As Integer) 'Handles ...
'get a "delay" value from somewhere, if you like
Dim newDelayTask As New DelayThread(ID, delay) 'added delay here
AddHandler newDelayTask.onDelayUp, AddressOf DoSomething
Dim t As New System.Threading.Thread( _
New System.Threading.ThreadStart(AddressOf newDelayTask.DelayProc))
t.Priority = Threading.ThreadPriority.Normal 'whatever priority
t.Start()
End Sub
Таким образом, каждый раз, когда происходит событие, вы запускаете новый поток, который ожидает вашего времени задержки, выполняет DoSomething, а затем завершает свою работу, очищаясь в процессе.
Здесь вам понадобится процедура «DoSomething»:
'declare this somewhere
Delegate Sub dlgDoSomething(ByVal ID As Integer)
Public Sub DoSomething(ByVal ID As Integer) 'hooked to onDelayUp @ runtime above
'using "Me" here - if DoSomething is somewhere else
'you may need to refer to the main UI form instead
Me.Invoke(New dlgDoSomething(AddressOf uiDoSomething), New Object() {ID})
End Sub
Процедура DoSomething будет вызываться из каждого потока, поэтому она должна вызываться в основном потоке пользовательского интерфейса - тогда потребуется:
Public Sub uiDoSomething(ByVal ID As Integer)
' Do Something with ID - UI thread is now executing this so you are safe
End Sub
Если важно знать точный порядок событий - знать, когда они прибыли и в каком порядке - тогда вы можете добавить временную метку в SomeEventFromExtDevice и передать ее также.
Возможно, вы также захотите добавить некоторую обработку для закрытия приложения - здесь нет никаких проверок, чтобы убедиться, что потоки не пытаются маршалировать в основную форму после ее удаления, например.