C# 任务不像我期望的那样
C# Task does not act like what I expect
首先,我用线程实现了测试逻辑:
public void ThreadProc()
{
Console.Write("s");
Thread.Sleep(1000);
Console.Write("e");
}
public void TestByThread()
{
for (var i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(ThreadProc));
t.Start();
}
}
当运行 TestByThread()时,结果是这样的:
ssssssssseeeeeeeeee
但是当涉及到任务时...
public void TestByTask()
{
for (var i = 0; i < 10; i++)
{
Task.Run(() =>
{
Console.Write("s");
Thread.Sleep(1000);
Console.Write("e");
});
}
}
执行TestByTask()时,结果很奇怪:
ssssssseesesseeeeeeee
不仅字符顺序不同,输出速度也不同。
任务和线程有什么区别?
Thread.Start()
启动一个新线程,其中 Task.Run()
安排一个任务。然后任务由下一个可用的工作线程执行。可能会创建一个新线程,但不要依赖它。
在第一个示例中,您手动创建了 10 个线程,并且 运行 它们是并行的。并且由于每个线程在写入 "e"
之前等待 1 秒,因为并行性,所有 10 "s"
都已经写入。
当您使用 Task.Run
时,您是在指示 CLR 在池中有一个可用的 worker 时立即启动一个新任务。通常你会在池中拥有与 CPU 个核心一样多的工作人员(但这不是保证),所以基本上即使你调用 Task.Run
10 次,这并不意味着 10 个线程将启动立即工作。恰恰相反,它只会启动池中当前可用的任务,然后其他任务将等待第一个任务完成后再重新开始。
当您调用 Thread.Start
时,会创建一个新线程,所有线程都会打印 s
,然后等待,所有线程都会打印 e
.
在 Task.Run
的情况下,任务在线程池中只有很少的线程。这似乎有点奇怪,因为池中只有 7 个线程可用,可能是一些线程正忙于做某事。所以7次任务打印s
,全部进入休眠状态,但是队列中还有更多的任务根本没有开始。
当池中的一些任务完成时(打印 e
),这些任务可用于 运行 新任务,因此它随后开始其余待处理任务。
首先,我用线程实现了测试逻辑:
public void ThreadProc()
{
Console.Write("s");
Thread.Sleep(1000);
Console.Write("e");
}
public void TestByThread()
{
for (var i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(ThreadProc));
t.Start();
}
}
当运行 TestByThread()时,结果是这样的:
ssssssssseeeeeeeeee
但是当涉及到任务时...
public void TestByTask()
{
for (var i = 0; i < 10; i++)
{
Task.Run(() =>
{
Console.Write("s");
Thread.Sleep(1000);
Console.Write("e");
});
}
}
执行TestByTask()时,结果很奇怪:
ssssssseesesseeeeeeee
不仅字符顺序不同,输出速度也不同。
任务和线程有什么区别?
Thread.Start()
启动一个新线程,其中 Task.Run()
安排一个任务。然后任务由下一个可用的工作线程执行。可能会创建一个新线程,但不要依赖它。
在第一个示例中,您手动创建了 10 个线程,并且 运行 它们是并行的。并且由于每个线程在写入 "e"
之前等待 1 秒,因为并行性,所有 10 "s"
都已经写入。
当您使用 Task.Run
时,您是在指示 CLR 在池中有一个可用的 worker 时立即启动一个新任务。通常你会在池中拥有与 CPU 个核心一样多的工作人员(但这不是保证),所以基本上即使你调用 Task.Run
10 次,这并不意味着 10 个线程将启动立即工作。恰恰相反,它只会启动池中当前可用的任务,然后其他任务将等待第一个任务完成后再重新开始。
当您调用 Thread.Start
时,会创建一个新线程,所有线程都会打印 s
,然后等待,所有线程都会打印 e
.
在 Task.Run
的情况下,任务在线程池中只有很少的线程。这似乎有点奇怪,因为池中只有 7 个线程可用,可能是一些线程正忙于做某事。所以7次任务打印s
,全部进入休眠状态,但是队列中还有更多的任务根本没有开始。
当池中的一些任务完成时(打印 e
),这些任务可用于 运行 新任务,因此它随后开始其余待处理任务。