Just take the lock so that OnStop() cannot run at the same time as Elapsed event handler:
Protected Overrides Sub OnStop()
SyncLock Me
_timer.Stop()
End SyncLock
End Sub
Which can race, the Elapsed event handler might already be scheduled to run but didn't yet enter the lock. So verify that the timer is still enabled:
Private Sub _timer_Elapsed(ByVal sender As Object, ByVal e As EventArgs)
SyncLock Me
If Not _timer.Enabled Return
'' etc..
Favor a dedicated lock object instead of Me. And watch out for the 30 seconds that the service controller is willing to wait before giving up, you are getting close.