1

I am trying to pass an integer value into a ElapsedEventHandler so I can do logic based on the integer passed in. However, when the Event is raised, the value coming in is not the value I initialized it to. I may not be understanding completely how the delegate works.

class Example
{
    Dictionary<int, Timer> timer;

    public Example()
    {
        timer = new Dictionary<int, timer>();
        for(int i = 0; i < 12; ++i)
        {
            timer.Add(i, new Timer(5000));
            timer[i].Elapsed += delegate { TimerTickCustom(i); };
        }
    }
    public void Process() // called each cycle
    {
        for(int i = 0; i < 12; ++i)
        {
            timer[i].Start();
        }
    }
    private void TimerTickCustom(int i)
    {
        // The value of i coming in does not match the dictionary key.
    }
}
user2970916
  • 1,146
  • 3
  • 15
  • 37
  • 1
    Try making a new object that extends `Timer` and creating a field there! – Ilan Jan 12 '17 at 21:47
  • Would I still be using the delegate at that point? – user2970916 Jan 12 '17 at 21:55
  • @Ilan321 You don't create a new timer every time you want to use data in the `tick` handler. That doesn't make conceptual sense (it's not a different kind of timer) it's way more work, and it's simply unnecessary. – Servy Jan 12 '17 at 22:26

1 Answers1

1

It depends on where the local value i is for the delegate to regard it as "specific" to it's scope. As i is defined outside the loop, the delegate doesn't define it's own "copy" of this variable - as all the delegates expect the same i.

What you need to do is assign it to a variable that's "on the same level" as the delegate itself.

Not sure if I'm using the right language here to explain it. But this should work:

class Example
{
    Dictionary<int, Timer> timer;

    public Example()
    {
        timer = new Dictionary<int, Timer>();
        for(int i = 0; i < 12; ++i)
        {
            int iInScopeOfDelegate = i;
            timer.Add(i, new Timer(5000));
            timer[i].Elapsed += delegate { TimerTickCustom(iLocalToDelegate ); };
        }
    }
    public void Process() // called each cycle
    {
        for(int i = 0; i < 12; ++i)
        {
            timer[i].Start();
        }
    }
    private void TimerTickCustom(int i)
    {
        // The value of i coming in does not match the dictionary key.
    }
}

There's some interesting discussion if you know which words to type into the search engine (which of course, you can't really know until someone tells you).

Community
  • 1
  • 1
Joe
  • 6,773
  • 2
  • 47
  • 81