Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

242
Views
esperar en la tarea para finalizar, con operaciones después de 'esperar'

Sé que puedo recibir un voto negativo, pero aparentemente no entiendo lo suficiente sobre async-await y las preguntas/respuestas que encontré, y los artículos que encontré, no me ayudaron a encontrar una respuesta para esta pregunta:

¿Cómo puedo hacer que se imprima "2"? O en realidad, ¿POR QUÉ no se imprime 2, tanto en await t como en t.Wait() ?:

 static Task t; public static async void Main() { Console.WriteLine("Hello World"); t = GenerateTask(); await t; //t.Wait(); Console.WriteLine("Finished"); } public static Task GenerateTask() { var res = new Task(async () => { Console.WriteLine("1"); await Task.Delay(10000); Console.WriteLine("2"); }); res.Start(); return res; }

Editar: estoy creando una tarea y devolviéndola porque en la vida real necesito esperar en esta tarea más adelante, desde un método diferente.

Edit2: await Task.Delay es solo un marcador de posición para una espera de la vida real en una función diferente.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Imprimiendo '2'

El 2 se imprime realmente, 10 segundos después de que se imprime el 1. Puede observar esto si agrega Console.ReadLine(); después de imprimir 'Terminado'.

la salida es

 Hello World 1 Finished 2

¿Qué está pasando?

Cuando espera t (que es res en el método GenerateTask ), está esperando la Tarea creada y no la tarea que res creó.

Cómo arreglar (manera elegante)

Deberá esperar tanto la tarea externa como la interna. Para poder esperar la tarea interior necesitas exponerla. Para exponerlo, debe cambiar el tipo de tarea de Task a Task<Task> y el tipo de retorno de Task a Task<Task> .

Podría verse algo como esto:

 public static async Task Main() { Console.WriteLine("Hello World"); var outerTask = GenerateTask(); var innerTask = await outerTask; // what you have await innerTask; // extra await Console.WriteLine("Finished"); Console.ReadLine(); } public static Task<Task> GenerateTask() // returns Task<Task>, not Task { var res = new Task<Task>(async () => // creates Task<Task>, not Task { Console.WriteLine("1"); await Task.Delay(TimeSpan.FromSeconds(10)); Console.WriteLine("2"); }); res.Start(); return res; }

La salida ahora es:

 Hello World 1 2 Finished

Cómo arreglar (manera fácil)

La tarea externa no es necesaria.

 public static async Task Main() { Console.WriteLine("Hello World"); var t = GenerateTask(); await t; Console.WriteLine("Finished"); Console.ReadLine(); } public static async Task GenerateTask() { Console.WriteLine("1"); await Task.Delay(TimeSpan.FromSeconds(10)); Console.WriteLine("2"); }
over 4 years ago · Santiago Trujillo Report

0

Parece que es porque el constructor de la nueva tarea solo toma algún tipo de acción (por lo que la tarea nunca se devuelve aunque sea asíncrona). Entonces, esencialmente, lo que está haciendo es un vacío asíncrono con su delegado. Tu await Task.Delay(10000) está regresando y la acción se considera 'hecha'.

Puede ver esto si cambia la await Task.Delay(10000) a Task.Delay(10000).Wait() y elimina la sincronización del delegado.

Sin embargo, en otra nota, nunca antes había visto o usado personalmente una nueva tarea. Task.Run() es una forma mucho más estándar de hacerlo, y permitirá que se use la espera. También significa que no tiene que llamar a Start() usted mismo.

También es posible que ya sepa esto, pero en este caso específico no necesita una nueva tarea en absoluto. Puedes hacer esto:

 public static async Task GenerateTask() { Console.WriteLine("1"); await Task.Delay(10000); Console.WriteLine("2"); }

Con respecto a tus ediciones

Reemplazar su GenerateTask con lo que escribí debería hacer lo que quiere. El async/await convertirá su método en una tarea que ha comenzado a ejecutarse. Esto es exactamente lo que está tratando de hacer, así que no estoy muy seguro de lo que está pidiendo con sus ediciones.

La tarea devuelta por GenerateTask puede esperarse cuando lo desee o no esperarse en absoluto. Casi nunca debería necesitar hacer new Task() . La única razón por la que puedo pensar es si desea retrasar la ejecución de la tarea hasta más tarde, pero habría mejores formas de evitarlo en lugar de llamar a new Task() .

Si usa la forma en que le mostré en su situación de la vida real, hágame saber qué no funciona al respecto y estaré encantado de ayudarlo.

over 4 years ago · Santiago Trujillo Report

0

Debe usar Task.Run() en lugar de crear una Task directamente:

 public static Task GenerateTask() { return Task.Run(async () => { Console.WriteLine("1"); await Task.Delay(10000); Console.WriteLine("2"); }); }

Task.Start() no funciona porque no comprende los delegados asíncronos y la tarea devuelta solo representa el comienzo de la tarea.

Tenga en cuenta que tampoco puede arreglar esto usando Task.Factory.StartNew() , por la misma razón.

Vea la publicación de blog de Stephen Cleary sobre este tema, de la cual cito:

[Task.Factory.StartNew()] No entiende los delegados asíncronos. En realidad, esto es lo mismo que el punto 1 en las razones por las que querría usar StartNew. El problema es que cuando pasa un delegado asíncrono a StartNew, es natural suponer que la tarea devuelta representa ese delegado. Sin embargo, dado que StartNew no comprende los delegados asíncronos, lo que esa tarea realmente representa es solo el comienzo de ese delegado. Este es uno de los primeros escollos que encuentran los codificadores cuando usan StartNew en código asíncrono.

Estos comentarios también se aplican al constructor de Task , que tampoco entiende los delegados asíncronos.

Sin embargo, es importante tener en cuenta que si ya está esperando en el código y no necesita paralelizar algún código vinculado a la computación, no necesita crear una nueva tarea en absoluto, solo use el código en su Task.Run() por sí solo servirá.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!