如何在MSBuild中并行运行任务

36

除非我对MSBuild的理解严重错误,否则任务将按它们在“Target”节点内部出现的文档顺序执行。

我希望能够指定两个任务(例如xcopy任务)可以并行运行。 我原本期望会有一个“Parallel”任务或类似的东西…?


请投票支持:https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/9604311-allow-custom-build-tools-to-run-in-parallel允许自定义构建工具并行运行。 - Trass3r
6个回答

39

21

我认为Visual Studio(MSBuild)已经可以并行编译文件,即使在同一个项目中也是如此。 - Baiyan Huang
2
@BaiyanHuang:我认为这是CL任务能够并行编译多个文件,但MSBuild中没有任何允许您自己使用该功能的内容。 - Joey

11

MSBuild有一个/m命令行开关,用于告诉它构建时使用的最大并发进程数。默认值为1。/m:x将使用x个进程。/m将使用计算机上的处理器数量。

我在Visual Studio的快捷方式中使用它来通过并行编译项目来更快地运行构建。Scott Hanselman在这里这里有一些相关文章。


2
谢谢,但我对在任务级别引入显式并行性很感兴趣;据我所见,这仅适用于非依赖的MSBuild项目。也许我会尝试将这些任务转换为单独的项目。 - Pete Montgomery

6
这里有一种并行运行msbuild目标的示例。其思想与…将此msbuild文件本身作为要构建的项目呈现相同。我从自己的问题中复制了它:通过C#评估在msbuild任务中定义的项
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build">
<Target Name="Build" DependsOnTargets="PrepareEnvironmentForBuild;MapDrives">
    <Exec Command="$(MSBuildBinPath)\msbuild /nologo /clp:Verbosity=quiet $(MSBuildThisFileFullPath) /t:TargetWithConfidentialSteps"/>
    <ItemGroup>
        <StepsToRunInParallel Include="$(MSBuildThisFileFullPath)">
            <Properties>TargetToInvoke=ParallelTarget1</Properties>
        </StepsToRunInParallel>
        <StepsToRunInParallel Include="$(MSBuildThisFileFullPath)">
            <Properties>TargetToInvoke=ParallelTarget2</Properties>
        </StepsToRunInParallel>
    </ItemGroup>
    <MSBuild Projects="@(StepsToRunInParallel)" BuildInParallel="true" StopOnFirstFailure="true" Targets="InvokeInParallelWithinThisProject"/>

</Target>
<Target Name="InvokeInParallelWithinThisProject">
    <MSBuild Projects="$(MSBuildThisFileFullPath)" Targets="$(TargetToInvoke)" StopOnFirstFailure="true"/>
</Target>
<Target Name="ParallelTarget1">
    <Message Text="Hello from ParallelTarget1"/>
</Target>
<Target Name="ParallelTarget2">
    <Message Text="Hello from ParallelTarget2"/>
</Target>
<Target Name="PrepareEnvironmentForBuild">
    <Message Text="Hello from PrepareEnvironmentForBuild"/>
</Target>
<Target Name="MapDrives">
    <Message Text="Hello from MapDrives"/>
</Target>
<Target Name="TargetWithConfidentialSteps">
    <Message Text="Hush! Verbosity on the wrapper does not affect the Exec call." Importance="High"/>
</Target>


1
记得使用 /m 标志调用 MSBuild.exe... 我没有这样做,很失望它没有并行构建... - Prof. Falken
你的脚本似乎可以工作,但是我的<PropertyGroup>值却没有传递给你生成的msbuild exe。有没有办法将所有这些值都传递过去? - ikku100
1
抱歉 @ikku100。我已经好几年没用 MSBuild 了 :-( - Parag Doke

3

我认为除了使用一些外部工具,没有其他方法可以做到这一点。我怀疑这是因为这会引入潜在的依赖问题,微软目前选择忽略它,从而让外部工具供应商解决这个问题(并收取相当高的费用)。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接