线程订单执行?

我有这个简单的代码:( 我在linqpad中运行

void Main() { for ( int i=0;idoWork(tmp)).Start(); } } public void doWork( int h) { h.Dump(); } 

int tmp=i; line用于捕获变量 – 因此每次迭代都有自己的值。

2个问题:

1)数字不是顺序的,而线程执行是!

2)有时我得到的数字少于 10个!

这里有一些执行输出:

在此处输入图像描述在此处输入图像描述在此处输入图像描述在此处输入图像描述

问题

1)为什么案例1正在发生,我该如何解决?

2)为什么案例2正在发生,我该如何解决?

不应期望它们是连续的。 每个线程都会在内核选择时获得优先级。 可能会发生这样的情况 ,它们看起来是连续的,完全取决于每个开始时的性质,但这只是纯粹的机会。

为了确保它们都完整 – 将每个新线程标记为IsBackground = false ,以便使可执行文件保持活动状态。 例如:

 new Thread(() => doWork(tmp)) { IsBackground = false }.Start(); 

线程以不可预测的顺序执行,如果主线程在其他线程之前完成,则不会获得所有数字(dump()将不会执行)。 如果你将你的线程标记为IsBackground = false,你将全部获得它们。 第一个没有真正的解决方案,除了不使用线程(或连接线程,这是真的一样)。

你不应该期望线程之间有任何顺序。

如果您启动一个新线程,它只会添加到操作系统的管理结构中。 最终,线程调度程序将出现并为线程分配时间片。 它可以以循环方式执行此操作,选择随机方式,使用一些启发式方法来确定哪一个看起来最重要(例如,拥有位于前台的Window的一个)等等。

如果输出的顺序是相关的,你可以在之后对它进行排序,或者 – 如果你知道工作开始之前的排序 – 使用一个数组,其中给每个线程一个索引,它应该写入它的结果。

以您的示例的方式创建新线程也非常慢。 对于微任务,使用线程池至少快一个数量级。

线程管理的本质是随机的。 你可以解决这两个任务,但开销太大了。

  1. 问题似乎是多个线程在控制台上(或者用于转储的内容)同意,同步机制的覆盖是可能的但是复杂并且会导致性能降低
  2. 在调用所有线程之前退出(请参阅@Marc Gravell的回答)

如果排序很重要,您可能希望利用共享队列并使用信号量来确保一次只有一个线程在队列顶部运行

您可以订购线程执行,但必须由您针对特定解决方案的特定问题专门完成。

例如:您希望该线程1,2,3完成您的代码的第1阶段,然后按照其ID(您已分配的这些ID)的顺序进入下一阶段。

您可以使用信号量来实现行为 – 搜索块同步和互斥以及测试和设置方法。