Estaba leyendo la publicación tips and tricks y pensé que probaría algunas de las cosas C# que nunca antes había hecho. Por lo tanto, el siguiente código no sirve para nada, pero es solo una "función de prueba" para ver qué sucede.C# ThreadStatic + miembros volátiles que no funcionan como se esperaba
De todos modos, tengo dos campos privados estáticas:
private static volatile string staticVolatileTestString = "";
[ThreadStatic]
private static int threadInt = 0;
Como se puede ver, estoy probando ThreadStaticAttribute y la volátil palabra clave.
De todos modos, tengo un método de prueba que tiene este aspecto:
private static string TestThreadStatic() {
// Firstly I'm creating 10 threads (DEFAULT_TEST_SIZE is 10) and starting them all with an anonymous method
List<Thread> startedThreads = new List<Thread>();
for (int i = 0; i < DEFAULT_TEST_SIZE; ++i) {
Thread t = new Thread(delegate(object o) {
// The anon method sets a newValue for threadInt and prints the new value to the volatile test string, then waits between 1 and 10 seconds, then prints the value for threadInt to the volatile test string again to confirm that no other thread has changed it
int newVal = randomNumberGenerator.Next(10, 100);
staticVolatileTestString += Environment.NewLine + "\tthread " + ((int) o) + " setting threadInt to " + newVal;
threadInt = newVal;
Thread.Sleep(randomNumberGenerator.Next(1000, 10000));
staticVolatileTestString += Environment.NewLine + "\tthread " + ((int) o) + " finished: " + threadInt;
});
t.Start(i);
startedThreads.Add(t);
}
foreach (Thread th in startedThreads) th.Join();
return staticVolatileTestString;
}
lo que cabe esperar para ver regresar de esta función es una salida como esta:
thread 0 setting threadInt to 88
thread 1 setting threadInt to 97
thread 2 setting threadInt to 11
thread 3 setting threadInt to 84
thread 4 setting threadInt to 67
thread 5 setting threadInt to 46
thread 6 setting threadInt to 94
thread 7 setting threadInt to 60
thread 8 setting threadInt to 11
thread 9 setting threadInt to 81
thread 5 finished: 46
thread 2 finished: 11
thread 4 finished: 67
thread 3 finished: 84
thread 9 finished: 81
thread 6 finished: 94
thread 7 finished: 60
thread 1 finished: 97
thread 8 finished: 11
thread 0 finished: 88
Sin embargo, lo Me sale esto:
thread 0 setting threadInt to 88
thread 4 setting threadInt to 67
thread 6 setting threadInt to 94
thread 7 setting threadInt to 60
thread 8 setting threadInt to 11
thread 9 setting threadInt to 81
thread 5 finished: 46
thread 2 finished: 11
thread 4 finished: 67
thread 3 finished: 84
thread 9 finished: 81
thread 6 finished: 94
thread 7 finished: 60
thread 1 finished: 97
thread 8 finished: 11
thread 0 finished: 88
La segunda "mitad" de la salida es la esperada (lo que supongo significa th en el campo ThreadStatic funciona como pensé), pero parece que algunas de las salidas iniciales se han "omitido" desde la primera "mitad".
Además, los hilos en la primera 'mitad' están fuera de servicio, pero entiendo que un hilo no se ejecuta inmediatamente tan pronto como llame a Start(); pero en su lugar, los controles internos del sistema operativo iniciarán los hilos como lo considere oportuno.
EDIT: No, no es, en realidad, yo sólo pensaba que eran porque mi cerebro no alcanza los números consecutivos
lo tanto, mi pregunta es: ¿Qué está pasando mal causar que pierda unas pocas líneas en el primera 'mitad' de la salida? Por ejemplo, ¿dónde está la línea 'thread 3 setting threadInt to 84'?
Ejecuto su código varias veces y siempre obtengo la salida esperada ... –
Apostaría que en algún lugar de la línea, la llamada a + = en la cadena obtiene el valor antes de que el hilo anterior lo haya configurado y el nuevo subproceso lo sobrescribe con el nuevo valor (por lo tanto, el subproceso 1 tuvo su salida omitida). – Charleh
@DannyChen Estoy en un quad-core, y ese no es el único código que se ejecuta en la aplicación; no sé si alguno de ellos tendría sentido. Puedo cargar todo el código en algún lugar (son solo dos archivos .cs) si lo desea. – Xenoprimate