循环内声明的值类型为何会保留上一次迭代的值?
为什么Parallel.ForEach循环中值类型会保留上一次迭代的值?
首先,完全不用在意首次发帖的小细节,你的问题描述得很清晰哦 😊
咱们来拆解这个问题的核心原因:
问题根源:线程池复用 + 闭包变量的生命周期
Parallel.ForEach为了提升性能,会复用线程池中的线程来处理不同的迭代任务。而如果你的值类型变量(比如代码里的j)是声明在parallelLoopBody这个委托的顶级作用域(比如Sub(s As String)的开头,而非内部循环里),VB的编译器会把这个变量“捕获”到一个自动生成的类中——这个变量的生命周期不再局限于单次迭代,而是会和执行委托的线程绑定。
当线程被复用来处理下一个迭代时,这个变量并不会自动重置为默认值(比如Integer的0),而是会保留上一次该线程处理迭代结束时的数值。
举个更直观的例子,如果代码逻辑是这样的:
Dim parallelLoopBody = Sub(s As String) Dim j As Integer ' 声明在委托的顶级作用域 For i As Integer = 1 To 10 For k As Integer = 1 To 10 j += (k * i) Next Next Console.WriteLine($"处理{s}后,j的值为:{j}") End Sub Parallel.ForEach(things, parallelLoopBody)
当线程1先处理thing1,结束后j有了一个累计值;如果线程1接着被复用处理thing2,j会直接从之前的累计值开始累加,而不是重置为0——这就是你看到“保留上一次迭代值”的原因。
解决方法:把变量放到正确的作用域
要避免这个问题,只需要把变量的声明放到需要重置的最内层作用域里:
- 如果
j需要在每次i循环开始时重置,就像你代码里写的那样,把Dim j As Integer放到For i As Integer = 1 To 10的内部; - 如果
j需要在每个Parallel.ForEach的迭代(也就是每个s的处理)开始时重置,那就在Sub(s As String)的开头显式给j赋值为0(比如Dim j As Integer = 0),或者把声明放到处理s的逻辑起始位置。
这样每次进入对应作用域时,变量都会被重新初始化,自然不会保留上一次迭代的值啦。
内容的提问来源于stack exchange,提问作者krew08
相关产品推荐
相关产品推荐

