El método Thread.Join tiene tres sobrecargas: Join() , Join(Int32) y Join(TimeSpan) . Para cada una de estas tres sobrecargas, existe la siguiente declaración en el documento de Microsoft :
Si el subproceso ya ha terminado cuando se llama a Join, el método regresa inmediatamente.
Si bien esta declaración tiene sentido para la sobrecarga de Join() , no especifica qué valor se devuelve para Join(Int32) y Join(TimeSpan) , por lo que probé la sobrecarga de Int32 en dos entornos diferentes:
Tenga en cuenta que la implementación de Linux/Docker se vuelve verdadera (como la de Windows) si el subproceso aún se está ejecutando cuando se llama Join y ha terminado después de la llamada. Solo devuelve falso si el hilo ha terminado antes de la llamada.
En mi opinión, Join siempre debería devolver verdadero en cualquier plataforma, entonces, ¿qué podría explicar este comportamiento inconsistente? ¿Me estoy perdiendo algo o es un error de .NET 5?
ACTUALIZAR
Según lo sugerido por @txtechhelp, aquí hay un .NET Fiddle con el código exacto que estoy probando.
Si ejecuto este código en Windows 10 (o en .NET Fiddle) obtengo el siguiente resultado:
Starting.. Sleeping 1200..expect T1 end before join In T1 Leaving T1 Join(100)..expect success Join(100) success! Done..Luego, si ejecuto este código usando mcr.microsoft.com/dotnet/runtime:5.0 en Docker Desktop (v. 3.1.0), obtengo el siguiente resultado:
Starting.. Sleeping 1200..expect T1 end before join In T1 Leaving T1 Join(100)..expect success Join(100) failed Done..ACTUALIZAR 2
En realidad, después de más pruebas, me di cuenta de que la prueba anterior solo falla si llamo a Join cuando la aplicación Docker se está descargando (es decir, después de recibir el evento AssemblyLoadContext.Default.Unloading , que es la señal enviada por Docker para informar que se va a apagar) la aplicación).
Así que aquí está la prueba exacta que incluso está fallando en .NET Fiddle:
public class Program { public static void Main() { System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += (arg) => { OnStopSignalReceived("application unloading"); }; } public static void T1() { System.Console.WriteLine("In T1"); System.Threading.Thread.Sleep(1000); System.Console.WriteLine("Leaving T1"); } private static void OnStopSignalReceived(string stopSignalSource) { System.Threading.Thread t1 = new System.Threading.Thread(T1); System.Console.WriteLine("Starting.."); t1.Start(); System.Console.WriteLine("Sleeping 1200..expect T1 end before join"); System.Threading.Thread.Sleep(1200); System.Console.WriteLine("Join(100)..expect success"); if (t1.Join(100)) { System.Console.WriteLine("Join(100) success!"); } else { System.Console.WriteLine("Join(100) failed"); } t1.Join(); System.Console.WriteLine("Done.."); } }