Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda expression, outer variables in multithread

Lets take this code:

public void Hit(int npage)
        {
            bool fetch = false;
            lock (pagesHit)
            {
                if (!pagesHit.Contains(npage))
                {
                    pagesHit.Add(npage);
                    fetch = true;
                }
            }
            if (fetch)
            {
                pageFiller.Completed += (s, e) =>
                    {
                        lock (pagesHit)
                        {
                            pagesHit.Remove(npage);
                        }
                    };
            }

        }

this function can be called from different threads. The goal is obviously to avoid fetching a page that is already scheduled for fetch. The filler object exposes an event that is subscribed via a lambda expression. My question is: can we say that the parameter npage is correctly handled in multithread scenario ? better: each event subscription receive its own npage parameter, or the last npage seen is propagate to all events ?

like image 595
Felice Pollano Avatar asked Oct 11 '11 08:10

Felice Pollano


2 Answers

Variable capture happens per the declaration scope of npage. The parameter npage is declared at the method level, and does not change within that method - so indeed, the use of npage is entirely thread-safe.

The problem you are avoiding would occur if you were changing a variable within its declared scope, typically a loop - i.e.

for(int npage = 0; npage < 100 ; npage++)
    Foo( (s,e) => DoSomething(npage) ); // not safe; npage shared between all

however, by breaking it into a method you avoid this, i.e.

for(int i = 0; i < 100; i++)
    Hit(i);
...
void Hit(int npage) {
    Foo( (s,e) => DoSomething(npage) ); // safe; npage is per-call
}
like image 154
Marc Gravell Avatar answered Oct 25 '22 06:10

Marc Gravell


Each Hit method invoke will have different values for npage reference.

In other words, each thread invoking this method will have its own npage.

That's because, for every thread invoking this method, its operations and event handler subscription will take place in different scopes, so, npage reference will point to scope's value.

like image 31
Matías Fidemraizer Avatar answered Oct 25 '22 08:10

Matías Fidemraizer