Reputation: 413
Can anyone explain why the following code works on some Win7 PC's but on some I get a MissingMethodException and the Timer.Elapsed event is never called.
Private Sub _timer2_Elapsed(ByVal sender As Object, ByVal e As System.EventArgs) Handles _timer2.Elapsed
_timer2.Enabled = False
Dispatcher.Invoke(Sub()
HandleSingleKeyPress(-1)
End Sub)
End Sub
After some investigation I have found that the following code works much better:-
Public Delegate Sub InvokedSubDelegate()
Private Sub _timer2_Elapsed(ByVal sender As Object, ByVal e As System.EventArgs) Handles _timer2.Elapsed
_timer2.Enabled = False
Dispatcher.Invoke(New InvokedSubDelegate(Sub()
HandleSingleKeyPress(-1)
End Sub))
End Sub
Not sure why the first approach works only sometimes but hope the solution can help someone else with similar problems.
Jerry
Upvotes: 0
Views: 352
Reputation: 942177
It doesn't sound like you are close to identifying the true problem. There certainly is more than one in that snippet.
A MissingMethodException is a DLL Hell problem. In other words, you are running your code with an old version of the assembly, one that doesn't yet have the method you are trying to call. You avoid DLL Hell by paying lots of attention when you deploy the assemblies. And by religiously incrementing the [AssemblyVersion]. In the VB.NET IDE that's done with Project + Properties, Application tab, Assembly Information button. This does explain why the 2nd snippet doesn't seem to have this problem, you are just less likely to be running with that old version of the assembly.
This does end up rather poorly when you use the System.Timers.Timer class. It is a nasty class. In a highly uncharacteristic lapse of judgement, Microsoft decided to swallow all exceptions that are raised in the Elapsed event handler. Which explains why the timer appears to be stop working, it just won't do what you asked it to do when the exception aborts the code. Favor the System.Threading.Timer class, it doesn't swallow exceptions. Or always using try/catch inside the Elapsed handler, albeit that it is pretty hard to figure out what to do when you catch. Environment.Exit() is wise.
But most of all, you are just using the entirely wrong timer. There's no point in using an asynchronous one when you make it synchronous again by using Dispatcher.Begin/Invoke(). Simply use a DispatcherTimer instead. Gets you the exact same outcome, minus the nastiness and overhead. And the need to ask this question.
Upvotes: 2