Zamierzałem zadać pytanie, ale zorientowałem się z wyprzedzeniem i postanowiłem zamieścić pytanie i odpowiedź - lub przynajmniej moje spostrzeżenia.Używanie Anonimowych Delegatów z .NET ThreadPool.QueueUserWorkItem
Podczas używania anonimowego uczestnika jako WaitCallback, gdzie ThreadPool.QueueUserWorkItem jest wywoływana w pętli foreach, wydaje się, że ta sama jedna wartość foreach jest przekazywana do każdego wątku.
List<Thing> things = MyDb.GetTheThings();
foreach(Thing t in Things)
{
localLogger.DebugFormat("About to queue thing [{0}].", t.Id);
ThreadPool.QueueUserWorkItem(
delegate()
{
try
{
WorkWithOneThing(t);
}
finally
{
Cleanup();
localLogger.DebugFormat("Thing [{0}] has been queued and run by the delegate.", t.Id);
}
}
}
Dla kolekcji 16 przypadkach rzeczą Czego zauważyć, że każda „rzecz” przeszedł do WorkWithOneThing odzwierciedlał ostatniej pozycji na liście "rzeczy.
Podejrzewam, że dzieje się tak, ponieważ delegat uzyskuje dostęp do zmiennej zewnętrznej "t". Zauważ, że eksperymentowałem również z przekazywaniem rzeczy jako parametrem dla anonimowego uczestnika, ale zachowanie pozostało nieprawidłowe.
Kiedy ponownie zakodowałem kod, aby użyć nazwanej metody WaitCallback i przekazałem Thing 't' do metody, viola ... Ithth of Things został poprawnie przekazany do WorkWithOneThing.
Przypuszczam, że to lekcja równoległości. Wyobrażam sobie również, że Parallel.For dla rodziny odnosi się do tego, ale ta biblioteka nie była dla nas opcją w tym momencie.
Mam nadzieję, że to oszczędza komuś innemu czas.
Howard Hoffman
Jeśli spróbujesz skompilować ten kod, nie dostaniesz błędzie „System.Threading.WaitCallback” nie bierze «argumenty 0»”jako określenie nie param – ram
Ram - Spróbuj zmienić powyższe oświadczenie: delegat() { ... } do delegat { ... } to właśnie miałem być przed dokonaniem mojej zmiany. Mam nadzieję, że to ci pomoże. –