我使用此example创建分区,并且在我的VS2015应用中完美运行。我尝试使用4.5.2框架将代码移动到VS2013,现在这段代码出错:
VS2013 12.0.40629.00更新5
body: (source, state, local) =>
说
错误5委托' System.Func< System.Tuple< long,long&gt ;,System.Threading.Tasks. ParallelLoopState,lo ng,AnonymousType#1,A nonymousType#1>&#39 ;不带3个参数
我发现了这个问题:Whats wrong in this Parallel.For Code?非常相似。但它似乎并不是同样的问题。
建议的答案在2013年没有任何语法错误,但没有使用分区,所以我不确定如何使我的代码适应那个。建议添加三个参数,我的已有三个参数。
这是我的代码的简化版本:
public void NearLinkParallelGeneration(avl_range avl_pending)
{
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount + 2
};
var partitions = Partitioner
.Create(
fromInclusive: avl_pending.begin,
toExclusive: avl_pending.end,
rangeSize: 100
)
.GetDynamicPartitions();
Parallel.ForEach(
source: partitions,
parallelOptions: parallelOptions,
localInit: () =>
{
NpgsqlConnection conn = new NpgsqlConnection(strConnection);
NpgsqlCommand cmd = new NpgsqlCommand();
conn.Open();
return new { Connection = conn, Command = cmd };
},
body: (source, state, local) => -- HERE IS THE ERROR
{
return local;
},
localFinally: local =>
{
local.Connection?.Dispose();
local.Command?.Dispose();
}
);
答案 0 :(得分:1)
我没有安装VS2013,因此我无法重现您的问题。但是,似乎编译器对选择哪个重载感到困惑。
您要复制的代码使用ForEach()
方法的Parallel.ForEach<TSource, TLocal> Method (IEnumerable<TSource>, ParallelOptions, Func<TLocal>, Func<TSource, ParallelLoopState, TLocal, TLocal>, Action<TLocal>)
重载。
您收到的错误消息表明编译器为您的呼叫选择了Parallel.ForEach<TSource, TLocal> Method (IEnumerable<TSource>, ParallelOptions, Func<TLocal>, Func<TSource, ParallelLoopState, Int64, TLocal, TLocal>, Action<TLocal>)
重载。也就是说,它希望代表不仅会收到source
,state
和local
值,还会收到当前项的index
。
目前缺乏在VS2013中测试代码的能力,我不完全确定为什么编译器选择了错误的重载。但我认为它可能与'Delegate 'System.Action' does not take 0 arguments.' Is this a C# compiler bug (lambdas + two projects)?中描述的问题有关。答案是,是的,它是编译器错误,因为延迟缓存导致编译器的重载元数据出错。
如果确实如此,您应该能够通过为lambda参数提供显式类型来解决此问题。不幸的是,在您的情况下,您使用TLocal
类型参数的匿名类型。所以你没有这个选项,除非你愿意声明一个命名类型而不是匿名类型。
另一种选择是放弃并遵循编译器关于你调用过载的想法。再一次,我不能自己测试,但我希望这会有效:
Parallel.ForEach(
source: partitions,
parallelOptions: parallelOptions,
localInit: () =>
{
NpgsqlConnection conn = new NpgsqlConnection(strConnection);
NpgsqlCommand cmd = new NpgsqlCommand();
conn.Open();
return new { Connection = conn, Command = cmd };
},
body: (source, state, index, local) // just add the 'index' parameter
{
return local;
},
localFinally: local =>
{
local.Connection?.Dispose();
local.Command?.Dispose();
}
);