C# 方法调用语句是否按照写入顺序同步执行?

C# 方法调用语句是否按照写入顺序同步执行?,c#,C#,例如: void Function1() { Function2(); Function3(); } Function3是否保证在每次调用Function1时都要等待Function2完成处理?是。Function3()等待直到Function2()执行完成 如果要独立调用它们,可以使用多线程概念 编辑:如注释所示,使用任务比线程好得多,因为它是一个更高级别的概念 请尝试独立地调用它们: using System.Threading.Tasks; static void Main(

例如:

void Function1()
{
  Function2();
  Function3();
}

Function3
是否保证在每次调用
Function1
时都要等待
Function2
完成处理?

是。
Function3()
等待直到
Function2()
执行完成

如果要独立调用它们,可以使用
多线程
概念

编辑:如注释所示,使用
任务
线程
好得多,因为它是一个
更高级别的
概念

请尝试独立地调用它们:

using System.Threading.Tasks;

static void Main(String[] args)
        { 
            Task t1 = new Task(Function2);
            Task t2 = new Task(Function3);
            t1.Start();
            t2.Start();
        }

在这里,我们不能保证执行流程是如何进行的,因为它们是独立运行的。

我不完全清楚“处理完成”是什么意思


但是
Function3()
只有在
Function2()
返回后才会调用
Function3()
,这就是它背后的全部思想,basic C#是一种命令式语言。

严格来说,不是。现代CPU为了提高性能,在引擎盖下进行了无数次优化。它们并行地执行事情,利用分支预测、管道等,这样它们就可以真正开始,甚至完成应该在尚未实际完成的事情之后发生的操作

然而,你不必担心这一点。我们煞费苦心地向您隐藏这些实现细节。虽然这些操作实际上可能不会按照给定的顺序进行,但您不可能观察到它们发生故障的事实。换句话说,您可以始终确保执行该代码后计算机的结果状态将与按顺序执行语句时的状态相同。如果处理器选择按顺序执行它们,将永远不会产生功能不同的程序

当然,正如评论中所说,这只适用于单个线程的执行。当有多个线程执行时,对于每个操作的执行顺序几乎没有保证。

说明:

3.10执行顺序

C#程序的执行过程中,每个程序的副作用 执行线程保留在关键执行点。一方 效应定义为对易失性字段的读取或写入,即对 非易失性变量、对外部资源的写入以及 抛出异常。关键执行点,在该点 这些副作用的顺序必须保留,以供参考 易失性字段(§10.5.3)、锁语句(§8.12)和线程 创建和终止。执行环境可以自由更改 C#程序的执行顺序,符合以下条件 限制条件:

  • 数据依赖性保留在执行线程中。也就是说,每个变量的值的计算就像 线程按原始程序顺序执行
  • 保留初始化顺序规则(§10.5.4和§10.5.5)
  • 关于易失性读写,保留副作用的顺序(§10.5.3)。此外,执行环境 如果可以推断出表达式的某一部分,则不需要对其求值 表达式的值未被使用,并且没有必要的副作用 产生(包括调用方法或访问 易失性字段)。当程序执行被 异步事件(如另一个线程引发的异常),它 不能保证可观察到的副作用在 原始程序顺序
因此,我认为这意味着,如果编译器或jitter可以证明您的两个函数调用可以重新排序,甚至跳过,那么编译器可以自由地这样做。实际上,我相信编译器或jitter不会对代码执行类似的优化,并且函数调用将同步执行。除此之外,CPU完全可以出于优化的原因重新排序执行,并且会这样做。当然,它不会以改变可观察输出的方式重新排序执行


在任何情况下,这都是没有意义的,因为每当语言规范或CPU体系结构允许重新排序时,只有当它对程序的意义没有影响时,才允许重新排序。所以,如果你有一个心理模型,说语句是同步有序执行的,你就不会受到任何伤害。如果编译器和/或CPU选择重新排序,它将以一种不会影响程序结果的方式进行排序。

当然可以,除非有一些异步内容正在进行。所谓处理,我的意思是函数2()中的任何逻辑都将在调用函数3()之前完成。@workingBee,如果是“任何逻辑”你的意思是,比如说,你用那个方法写的lambdas,那就不一定是真的。还有一些奇怪的
async
方法(和迭代器块)。所以一般来说并不简单。我建议您在新代码中使用
Task
s而不是
Thread
s<代码>任务
s有几个优点,几乎没有缺点。(虽然我不确定这个问题到底是关于什么的。)@svick:是的,绝对是。。。谢谢你宝贵的帮助point@svick:编辑了我的答案。您也可以使用Parallel.Invoke()独立调用它们。只要您在一个线程上。
“实际上,我不相信编译器或JITer会做到这一点”
几乎肯定会做到。现代CPU实际上从未一次只执行一个操作。他们在任何给定的时刻都会执行相当多的操作,而且他们也会非常频繁地重新排序操作以提高性能,因为他们可以保证结果是正确的