returns remarks generate example c# async-await task-parallel-library task

c# - remarks - Por qué la Tarea termina incluso en espera



remarks c# (3)

Hay excelentes respuestas aquí, pero me gustaría señalar lo obvio: Task.Factory.StartNew es completamente redundante, innecesario y se usa incorrectamente.

Si reemplazas

Task newTask = Task.Factory.StartNew(MainTask);

con

Task newTask = MainTask();

Obtendrás exactamente el comportamiento que esperas, sin perder otro hilo de subprocesos solo para iniciar otro subproceso de subprocesos. De hecho, si quisiera reescribir su ejemplo para ser más idiomático, usaría algo como esto:

static void Main (string[] args) { var task = MainTask() .ContinueWith(t => Console.WriteLine("Main State={0}", t.Status)); task.Wait(); } static async Task MainTask() { Console.WriteLine ("MainStarted!"); await Task.Delay(1000); Console.WriteLine ("Waiting Ended!!"); throw new Exception ("CustomException!"); Console.WriteLine ("NeverReaches here!!"); }

Este código solo usa una secuencia de grupo de subprocesos para el código después de la demora y vuelve a lanzar la excepción en la llamada task.Wait() ; es posible que desee hacer otra cosa, por supuesto.

Como nota al margen, incluso si no desea esperar explícitamente a que la tarea finalice, no debe usar while (true) {} para evitar que la aplicación finalice; una simple Console.ReadLine() funcionará solo también, y no va a impulsar uno de sus núcleos de CPU al 100% de utilización :)

Tengo un problema en el siguiente código:

static void Main (string[] args) { Task newTask = Task.Factory.StartNew(MainTask); newTask.ContinueWith ((Task someTask) => { Console.WriteLine ("Main State=" + someTask.Status.ToString () + " IsFaulted=" + someTask.IsFaulted+" isComplete="+someTask.IsCompleted); }); while (true) { } } static async Task MainTask() { Console.WriteLine ("MainStarted!"); Task someTask = Task.Factory.StartNew (() => { Console.WriteLine ("SleepStarted!"); Thread.Sleep(1000); Console.WriteLine ("SleepEnded!"); }); await someTask; Console.WriteLine ("Waiting Ended!!"); throw new Exception ("CustomException!"); Console.WriteLine ("NeverReaches here!!"); }

Solo quiero obtener Exception de la nueva tarea iniciada MainTask . Pero el resultado no fue el esperado.

MainStarted! Main State = RanToCompletion IsFaulted = False isComplete = True SleepStarted! SleepEnded! Waiting Ended!!

Como puede ver el resultado, la tarea finaliza antes de "¡La espera ha terminado!" registro de consola No tengo ni idea de por qué MainTask terminó incluso si MainTask await comando adentro. ¿Me perdí algo?


Modifiqué tu problema aquí para captar las excepciones.

static void Main(string[] args) { DoFoo(); Console.ReadKey(); } static async void DoFoo() { try { await Foo(); } catch (Exception ex) { //This is where you can catch your exception } } static async Task Foo() { await MainTask().ContinueWith((Task someTask) => { Console.WriteLine("Main State=" + someTask.Status.ToString() + " IsFaulted=" + someTask.IsFaulted + " isComplete=" + someTask.IsCompleted); }, TaskContinuationOptions.NotOnFaulted); } static async Task MainTask() { Console.WriteLine("MainStarted!"); Task someTask = Task.Run(() => { Console.WriteLine("SleepStarted!"); Thread.Sleep(1000); Console.WriteLine("SleepEnded!"); }); await someTask; throw new Exception("CustomException!"); Console.WriteLine("Waiting Ended!!"); }

debe usar TaskContinuationOptions.NotOnFaulted que significa que la tarea continuar con solo se ejecutará si la tarea primaria no tuvo excepciones.


Task.Factory.StartNew no entiende los delegados asíncronos, por lo que debe usar Task.Run en este caso y la excepción debería fluir.

Task.Factory.StartNew(MainTask);

es esencialmente equivalente a

Task.Factory.StartNew(() => MainTask);

que ignora la tarea devuelta desde MainTask y la excepción simplemente se traga.

Vea esta publicación en el blog para más detalles.

Intenta usar Task.Run en Task.Run lugar y obtendrás tu excepción:

void Main(string[] args) { Task newTask = Task.Run(MainTask); newTask.ContinueWith((Task someTask) => { Console.WriteLine("Main State=" + someTask.Status.ToString() + " IsFaulted=" + someTask.IsFaulted + " isComplete=" + someTask.IsCompleted); }); while (true) { } } static async Task MainTask() { Console.WriteLine("MainStarted!"); Task someTask = Task.Run(() => { Console.WriteLine("SleepStarted!"); Thread.Sleep(1000); Console.WriteLine("SleepEnded!"); }); await someTask; Console.WriteLine("Waiting Ended!!"); throw new Exception("CustomException!"); Console.WriteLine("NeverReaches here!!"); }