Stavo per pubblicare una domanda, ma ho capito prima e ho deciso di pubblicare la domanda e la risposta, o almeno le mie osservazioni.Utilizzo di delegati anonimi con .NET ThreadPool.QueueUserWorkItem
Quando si utilizza un delegato anonimo come WaitCallback, in cui ThreadPool.QueueUserWorkItem viene chiamato in un ciclo foreach, sembra che lo stesso valore foreach venga passato in ogni thread.
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);
}
}
}
Per una collezione di 16 istanze cosa in cose ho osservato che ogni 'cosa' passato a WorkWithOneThing corrisponde l'ultimo elemento della lista 'cose'.
Sospetto che ciò accada perché il delegato accede alla variabile esterna "t". Nota che ho anche provato a passare la cosa come parametro al delegato anonimo, ma il comportamento è rimasto scorretto.
Quando ho rielaborato il codice per utilizzare un metodo WaitCallback chiamato e passato la cosa 't' al metodo, viola ... l'istanza di I'thth è stata passata correttamente in WorkWithOneThing.
Una lezione di parallelismo, immagino. Immagino anche che il Parallel.Per la famiglia affronta questo, ma quella biblioteca non era un'opzione per noi a questo punto.
Spero che questo salvi qualcun altro un po 'di tempo.
Howard Hoffman
Se si tenta di compilare questo codice, non si ottiene un errore "System.Threading.WaitCallback' non tiene 'argomenti 0'", come si specifica alcun parametro – ram
Ram - Prova a cambiare la dichiarazione di cui sopra da: delegato() { ...} a delegato { ...} Questo è quello che avevo essere prima di fare il mio cambiamento. Spero che questo ti aiuti. –