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 alr开发者_JS百科eady 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 ?
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
}
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.
精彩评论