Cuándo usar la tarea.Delay, cuando usar hilo.¿Dormir?


Hay una(s) buena (s) regla (s) para cuándo usar la tarea .Delay versus Hilo.¿Dormir?

  • Específicamente, ¿hay un valor mínimo para prever que uno sea efectivo/eficiente sobre el otro?
  • Por último, desde Tarea.El retardo causa el cambio de contexto en una máquina de estado async/await, ¿hay una sobrecarga de usarlo?
Author: David Gardiner, 2013-11-20

5 answers

Use Thread.Sleep cuando desee bloquear el hilo actual.

Use Task.Delay cuando desee un retardo lógico sin bloquear el hilo actual.

La eficiencia no debe ser una preocupación primordial con estos métodos. Su uso principal en el mundo real es como temporizadores de reintento para operaciones de E/S, que están en el orden de segundos en lugar de milisegundos.

 230
Author: Stephen Cleary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-19 23:44:29

La mayor diferencia entre Task.Delay y Thread.Sleep es que Task.Delay está destinado a ejecutarse asincrónicamente. No tiene sentido usar Task.Delay en código síncrono. Es una MUY mala idea usar Thread.Sleep en código asíncrono.

Normalmente llamarás a Task.Delay() con la palabra clave await:

await Task.Delay(5000);

O, si desea ejecutar algún código antes del retraso:

var sw = new Stopwatch();
sw.Start();
Task wait = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await wait;

Adivina qué imprimirá esto? Funcionando durante 0.0070048 segundos. Si movemos el await wait por encima del Console.WriteLine en su lugar, se imprimirá Funcionando durante 5.0020168 segundos.

Veamos la diferencia con Thread.Sleep:

class Program
{
    static void Main(string[] args)
    {
        Task wait = asyncTask();
        syncCode();
        wait.Wait();
        Console.ReadLine();
    }

    static async Task asyncTask()
    {
        var sw = new Stopwatch();
        sw.Start();
        Console.WriteLine("async: Starting");
        Task wait = Task.Delay(5000);
        Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
        await wait;
        Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
        Console.WriteLine("async: Done");
    }

    static void syncCode()
    {
        var sw = new Stopwatch();
        sw.Start();
        Console.WriteLine("sync: Starting");
        Thread.Sleep(5000);
        Console.WriteLine("sync: Running for {0} seconds", sw.Elapsed.TotalSeconds);
        Console.WriteLine("sync: Done");
    }
}

Trate de predecir lo que esto imprimirá...

Async: Comenzando
asíncrona: Funcionando durante 0.0070048 segundos
sincronización: Comenzando
async: Corriendo por 5.0119008 segundos
async: Hecho
sincronización: Funcionando durante 5.0020168 segundos
sincronización: Hecho

También, es interesante notar que Thread.Sleep es mucho más preciso, la precisión de ms no es realmente un problema, mientras que Task.Delay puede tomar 15-30ms mínimo. La sobrecarga en ambas funciones es mínima en comparación con la precisión ms que tienen (uso Stopwatch Class if you need something more accurate). Thread.Sleep aún ata tu Hilo, Task.Delay suéltalo para hacer otro trabajo mientras esperas.

 145
Author: Dorus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-01 11:36:16

Si el subproceso actual está muerto y usas Thread.Sleep y se está ejecutando, entonces podrías obtener un ThreadAbortException. Con Task.Delay siempre puede proporcionar un token de cancelación y eliminarlo con gracia. Esa es una razón por la que elegiría Task.Delay. véase http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx

También estoy de acuerdo en que la eficiencia no es primordial en este caso.

 19
Author: Balanikas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-19 06:12:34

Quiero añadir algo. En realidad, Task.Delay es un mecanismo de espera basado en temporizador. Si miras la fuente encontrarás una referencia a una clase Timer que es responsable del retraso. Por otro lado Thread.Sleep en realidad hace que el hilo actual duerma, de esa manera solo está bloqueando y desperdiciando un hilo. En el modelo de programación asincrónica siempre debe usar Task.Delay() si desea que algo(continuación) suceda después de algún retraso.

 12
Author: crypted,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-14 10:16:51

Estas son operaciones funcionalmente equivalentes – simplemente crean una pausa, pero una tarea.El retraso está disponible.

 -3
Author: Anas Tina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-04 22:49:33