Task.Delay против Thread.Sleep разница - PullRequest
5 голосов
/ 29 марта 2020
private static async Task MainFunc()
{
    var watch = System.Diagnostics.Stopwatch.StartNew();

    List<Task<int>> list = new List<Task<int>>();

    for (int i = 1; i <= 3; i++)
    {
        list.Add(TaskFunc(i));
    }

    var taskResult = await Task.WhenAll(list);

    foreach (var item in taskResult)
    {
        Console.Write($"i= {item}.{ Environment.NewLine }");
    }

    list.Clear();

    watch.Stop();
    var elapsedMs1 = watch.ElapsedMilliseconds;

    Console.WriteLine($"Total execution time: { elapsedMs1 }");
    Console.WriteLine();


    watch.Restart();


    for (int i = 1; i <= 3; i++)
    {
        list.Add(Task.Run(() => ThreadFunc(i)));
    }

    var threadResult = await Task.WhenAll(list);

    foreach (var item in threadResult)
    {
        Console.Write($"i= {item}.{ Environment.NewLine }");
    }

    watch.Stop();
    var elapsedMs2 = watch.ElapsedMilliseconds;

    Console.WriteLine($"Total execution time: { elapsedMs2 }");
}

private static async Task<int> TaskFunc(int i)
{

    if (i == 1)
        await Task.Delay(2000);
    else if (i == 2)
        await Task.Delay(1000);
    else if (i == 3)
        await Task.Delay(5000);

    return i;
}

private static int ThreadFunc(int i)
{
    if (i == 1)
        Thread.Sleep(2000);
    else if (i == 2)
        Thread.Sleep(1000);
    else if (i == 3)
        Thread.Sleep(5000);

    return i;
}

В этом примере есть две функции, TaskFunc и ThreadFunc, которые вызываются из MainFunc отдельно. Мне любопытно, почему второй метод, кажется, не имеет никакого эффекта, и, кажется, пропущен. Кажется, даже Thread.Sleep(...) не выполняется.

Time comparison

Как видите, общее время выполнения для ThreadFunc очень короткое, даже хотя таймеры сна должны быть одинаковыми для обоих методов. Кроме того, i всегда установлен на 4. Я полагаю, что основной поток делает что-то не так. Может кто-нибудь объяснить, что здесь происходит?

1 Ответ

9 голосов
/ 29 марта 2020

Проблема здесь в определении объема. i, который вы используете внутри Task.Run(() => TheadFunc(i)), не является новым целым числом, а, поскольку он является делегатом, значение i будет извлечено только после выполнения делегата .

Это приводит к тому, что i будет 4 во всех случаях, так как ваш for -l oop значительно увеличивает его. Но поскольку у вас нет условия if для значения 4, оно не будет выполнять никаких задержек с Thread.Sleep(...).

...