1

I'm using TimeSetEvent and its callback function is working but after a few seconds it fails EVEN if the callback function does no work at all:

// Vars
private TimerEventHandler timerRef;
private uint timerId = 0;

//Later, where I use TimeSetEvent
timerRef = new TimerEventHandler(CallbackFunction);
timerId = timeSetEvent(200, 10, timerRef, UIntPtr.Zero, TIME_KILL_SYNCHRONOUS | TIME_PERIODIC);

Even with 200ms delay it's not working properly.

private void CallbackFunction(uint id, uint msg, UIntPtr userCtx, UIntPtr uIntPtr, UIntPtr intPtr)
{

// Even if this is empty, it will fail
}

I either get NullReferenceException(most of the times) or AccessViolationException (occasionally). I suspect both coming from the same problem.

Funny thing, I have exactly the same structure in another class and it works. I copied that class and here... It doesn't. I get this error.

I don't understand why it's not working (and in the other class it does) and how to solve it.

PD: timerId returns an integer different than 0. I don't understand where this null comes frmo, if I comment TimerId = TimeSetEvent... Code won't fail.

сами J.D.
  • 483
  • 2
  • 5
  • 19
  • In which line of code does it throw that exception? – rene Sep 06 '15 at 21:35
  • It doesn't say, hence I couldn't locate it. However, I commented all the code and was adding function by function and realized that when I call this TimeSetEvent it will crash soon, after 20 iterations or so. Even if the function does nothing. However, not calling it "works" (= doesn't crash, but obviously I need that timer). – сами J.D. Sep 06 '15 at 21:48
  • What does `timeSetEvent` do? – Rob Sep 06 '15 at 22:11
  • It's like Timers.Timer but much more precise. It's called Timer multimedia and has icnredible high precision for windows up to 1ms). – сами J.D. Sep 06 '15 at 22:17
  • If you don't show us an [MCVE] it is impossible for us to answer. I suspect the issue is caused by a managed object that gets gc-ed or moved. Consider keeping that TimerEventhandler in scope and maybe wrap it in a `fixed` statement to prevent it being moved around in memory. http://stackoverflow.com/questions/2490912/what-are-pinned-objects – rene Sep 07 '15 at 06:14
  • It's very complex that's why I didn't know how to properly posted it. We found the problem, I'm going to post the answer now. – сами J.D. Sep 07 '15 at 17:52

1 Answers1

0

After couple of days with my workmate reviewing more and more code we found the problem. Have to say the question didn't have enough information to solve it, but we couldn't know. It's very complex program and we couldn't imagine we needed code from other classes.

The code above is in Class B. This is called from Class A. Turns out Class A is destroyed occasionally and as TimeSetEvent is pinvoked (unmanaged) it carries on working. Therefore, when it tries to look for the callback function it has been disposed along with all contents from Class B and it gives a null reference exception.

The solution is to implement a method in Class B that kills the timer before removing Class A. Then, it will be safe to delete Class A and Class B won't make the application crash.

сами J.D.
  • 483
  • 2
  • 5
  • 19
  • The debugger normally always generates [a diagnostic](https://msdn.microsoft.com/en-us/library/43yky316%28v=vs.110%29.aspx) for this. A thorough review of debugger settings would probably be appropriate. Proper solution is GCHandle.Alloc() – Hans Passant Sep 07 '15 at 18:11
  • Hey @HansPassant, can you provide some example or more context about GCHandle.Alloc()? `TimerEventHandler` is a delegate and from what I can read (http://manski.net/2012/06/pinvoke-tutorial-pinning-part-4/) they can't be pinned. _Note also that you don’t need (and actually can’t) pin delegates. You need, however, to extend the lifetime of the delegate for as long as it can be called from unmanaged code._ Not sure either about how to check for the diagnostic. – сами J.D. Sep 09 '15 at 08:07
  • 1
    Nothing to do with pinning, you pass GCHandleType.Normal. So that the GC always sees an object reference and won't collect it. – Hans Passant Sep 09 '15 at 08:17
  • Interesting. Will check how to do it if the Dispose I implemented fails! – сами J.D. Sep 09 '15 at 08:58