假设我有一个包含元数据的ItemGroup需要一些时间来构建(10秒):
<Target Name="BuildItemGroup">
<ItemGroup>
<File Include="5">
<Value>5a</Value>
</File>
<File Include="4">
<Value>4a</Value>
</File>
...
</ItemGroup>
<Message Text="Wait 10 seconds..." Importance="High" />
</Target>
我将在递归的MSBuild任务中几次使用相同的ItemGroup:
<Target Name="Recursive" DependsOnTargets="BuildItemGroup" Condition="$(Value) > 0" >
<PropertyGroup>
<Value>$([MSBuild]::Subtract($(Value), 1))</Value>
</PropertyGroup>
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value)" />
</Target>
<PropertyGroup>
<Value>5</Value>
</PropertyGroup>
<Target Name="Default" DependsOnTargets="Recursive" />
4个循环完成Recursive
任务需要额外40秒。有没有办法以这种方式缓存ItemGroup以进行循环使用?
答案 0 :(得分:1)
不,调用MSBuild任务将创建新的上下文,该上下文将重新评估所有属性和项目。 在parent \ child上下文之间传递数据的唯一方法是属性(以及成为全局属性的环境变量)。
根据此列表的大小 - 您可以尝试将其作为属性传递(丢失元数据)并在子msbuild上下文中重新创建itemgroup。
或者您可以使用C#切换到内联任务,并使用完整的C#功能切换到任何您想要的内容 - 例如将数据保存到磁盘并从文件中读回。
更新:最后我做了这样的内联任务。实际上,这是一个要保存的任务和另一个 - 从磁盘加载持久化的项目。有点难看的代码 - 我必须为Item和元数据类创建一个可序列化的副本。但它作为一个PoC已经足够好了。它无法保证在多线程环境中安全运行,尤其是在200多个项目的情况下。 See the code in this repository