You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Microsoft.CodeAnalysis.CSharp.Scripting时Parallel.For未等待完成的问题

问题分析与解决:Parallel.For操作非线程安全集合导致元素数量不足

你的代码中Parallel.For并非未等待完成就返回,问题核心是**List<T>不是线程安全集合**,多线程并发调用Add方法会引发竞争条件,导致部分元素添加失败,最终返回的列表元素数量不足且结果不稳定。这既不是Microsoft.CodeAnalysis.CSharp.Scripting的Bug,也不是该场景不受支持。

问题根源

List<T>的Add方法内部会修改私有数组和计数变量,这些操作没有线程同步机制。当多个线程同时执行Add时,可能出现以下情况:

  • 两个线程同时读取当前计数,基于同一个值插入元素,导致其中一个元素被覆盖
  • 数组扩容过程中,线程间操作冲突导致部分元素未被正确写入

而Parallel.For本身会等待所有迭代任务完成后才继续执行后续代码,返回结果异常和Parallel.For的等待机制无关。

修复方案

方案1:使用线程安全集合ConcurrentBag<T>

将List<string>替换为System.Collections.Concurrent命名空间下的ConcurrentBag<string>,它专门为多线程场景设计,所有操作都是线程安全的:

var code = @"
var myList = new ConcurrentBag<string>();
Parallel.For(0, 300, i  =>
{
    myList.Add(i.ToString());
});
return myList.ToList();";

方案2:对List.Add操作加锁

通过显式加锁确保同一时间只有一个线程执行Add操作,避免竞争:

var code = @"
var myList = new List<string>();
var lockObj = new object();
Parallel.For(0, 300, i  =>
{
    lock(lockObj)
    {
        myList.Add(i.ToString());
    }
});
return myList;";

方案3:使用PLINQ简化实现

如果只是需要生成包含指定范围字符串的列表,用PLINQ可以更简洁地完成线程安全的集合生成:

var code = @"
return Enumerable.Range(0, 300).AsParallel().Select(i => i.ToString()).ToList();";

内容的提问来源于stack exchange,提问作者opitzh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:55:19