MSBuild-如何创建;“临界截面”;

MSBuild-如何创建;“临界截面”;,msbuild,mutex,Msbuild,Mutex,我有一个多个项目的并行构建,每个项目在某个时间点都会调用任务。此exec任务正在运行3pty工具,如果此工具的另一个实例正在运行,该工具将崩溃。在msbuild中是否有一些实现“互斥”的本机方法 显而易见的解决方案(有效)是使构建同步,但这会减慢整个构建的速度。最后,我编写了自己的msbuild扩展库,如下所示 msbuild部分: <UsingTask TaskName="MutexExec" AssemblyFile="$(CommonTasksAssem

我有一个多个项目的并行构建,每个项目在某个时间点都会调用
任务。此exec任务正在运行3pty工具,如果此工具的另一个实例正在运行,该工具将崩溃。在msbuild中是否有一些实现“互斥”的本机方法


显而易见的解决方案(有效)是使构建同步,但这会减慢整个构建的速度。

最后,我编写了自己的msbuild扩展库,如下所示

msbuild部分:

<UsingTask TaskName="MutexExec" AssemblyFile="$(CommonTasksAssembly)" />

C部分:

//
// 
// 
使用制度;
使用系统诊断;
使用系统线程;
使用Microsoft.Build.Framework;
使用Microsoft.Build.Tasks;
/// 
///类似于执行任务,但具有关键部分
/// 
公共类mutexec:Exec
{
/// 
///获取或设置互斥体名称
/// 
[必需]
公共字符串MutexName{get;set;}
/// 
公共重写bool Execute()
{
var超时=TimeSpan.FromMinutes(5);
var stopwatch=stopwatch.StartNew();
while(秒表时间<超时)
{
布尔创造了新的;
使用(var mutex=new mutex(true,this.MutexName,out createdNew))
{
如果(createdNew)
{
bool result=base.Execute();
尝试
{
this.Log.LogMessage(MessageImportance.Normal,“Releasing{0}”,this.MutexName);
mutex.ReleaseMutex();
}
捕获(例外e)
{
this.Log.LogError(“失败释放{0}-{1}”,this.MutexName,e);
}
返回结果;
}
}
LogMessage(MessageImportance.Normal,“等待{0}-ellapsed{1}”,this.MutexName,stopwatch.appeased);
睡眠(5000);
继续;
}
this.Log.LogError(“在{1}中获取{0}失败。”,this.MutexName,超时);
返回false;
}
}
// <PackageReference Include="Microsoft.Build.Utilities.Core" Version="16.9.0" />
// <PackageReference Include="Microsoft.Build.Tasks.Core" Version="16.9.0" />
// <PackageReference Include="Microsoft.Build.Framework" Version="16.9.0" />

using System;
using System.Diagnostics;
using System.Threading;
using Microsoft.Build.Framework;
using Microsoft.Build.Tasks;

/// <summary>
/// Like a Exec task, but with critical section
/// </summary>
public class MutexExec : Exec
{
    /// <summary>
    ///     Gets or sets mutex name
    /// </summary>
    [Required]
    public string MutexName { get; set; }

    /// <inheritdoc />
    public override bool Execute()
    {
        var timeout = TimeSpan.FromMinutes(5);
        var stopwatch = Stopwatch.StartNew();
        while (stopwatch.Elapsed < timeout)
        {
            bool createdNew;
            using (var mutex = new Mutex(true, this.MutexName, out createdNew))
            {
                if (createdNew)
                {
                    bool result = base.Execute();
                    try
                    {
                        this.Log.LogMessage(MessageImportance.Normal, "Releasing {0}", this.MutexName);
                        mutex.ReleaseMutex();
                    }
                    catch (Exception e)
                    {
                        this.Log.LogError("Failure releasing {0} - {1}", this.MutexName, e);
                    }

                    return result;
                }
            }

            this.Log.LogMessage(MessageImportance.Normal, "Waiting for {0} - ellapsed {1}", this.MutexName, stopwatch.Elapsed);
            Thread.Sleep(5000);
            continue;
        }

        this.Log.LogError("Failed to acquire {0} in {1}.", this.MutexName, timeout);
        return false;
    }
}