Выполнение метода в первый раз всегда более затратно: сборки загружаются лениво, а метод еще может не быть JITted.
Например, если мы возьмем ваш тест (заменив DateTime на Stopwatch для точности)и еще раз позвоните Task.Factory.StartNew
:
static void Main(string[] args)
{
var sw = Stopwatch.StartNew();
new Thread(() => { ExecuteAsyn("Thread", sw); }).Start();
Console.WriteLine("Using Thread: " + sw.Elapsed);
sw = Stopwatch.StartNew();
Task g = Task.Factory.StartNew(() => ExecuteAsyn("TPL", sw));
Console.WriteLine("Using TPL: " + sw.Elapsed);
g.Wait();
sw = Stopwatch.StartNew();
g = Task.Factory.StartNew(() => ExecuteAsyn("TPL", sw));
Console.WriteLine("Using TPL: " + sw.Elapsed);
g.Wait();
Console.ReadKey();
}
private static void ExecuteAsyn(string source, Stopwatch sw)
{
Console.WriteLine("Hello World! Using " + source + " the difference between initialization and execution is " + (sw.Elapsed));
}
Результат на моем компьютере:
Использование темы: 00: 00: 00.0002071
Hello World!При использовании Thread разница между инициализацией и выполнением составляет 00: 00: 00.0004732
При использовании TPL: 00: 00: 00.0046301
Hello World!При использовании TPL разница между инициализацией и выполнением составляет 00: 00: 00.0048927
При использовании TPL: 00: 00: 00.0000027
Hello World!При использовании TPL разница между инициализацией и выполнением составляет 00: 00: 00.0001215
. Мы видим, что второй вызов выполняется быстрее, чем первый, на три порядка.
Использованиереальный тестовый фреймворк (например, BenchmarkDotNet), мы можем получить гораздо более надежные результаты:
Method | Mean | Error | StdDev |
-------- |-----------:|----------:|----------:|
Threads | 137.426 us | 1.9170 us | 1.7932 us |
Tasks | 2.384 us | 0.0322 us | 0.0301 us |
Тем не менее, несколько дополнительных замечаний:
Ваше сравнениене честно.Вы сравниваете создание потока с постановкой задачи в пул потоков через API задач.Справедливости ради, вместо этого следует использовать ThreadPool.UnsafeQueueWorkItem
(что позволяет использовать пул потоков без API задачи)
Независимо от того, использовать ли Thread или Task, не должно зависеть от производительности.Это действительно больше вопрос удобства.Весьма маловероятно, что разрыв в производительности будет иметь какое-либо значение в вашем приложении, если вы не имеете дело с низкой задержкой или очень высокой пропускной способностью.