【问题标题】:MSBuild - how to create "critical section"MSBuild - 如何创建“关键部分”
【发布时间】:2020-10-30 10:02:10
【问题描述】:

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

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

【问题讨论】:

    标签: msbuild mutex


    【解决方案1】:

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

    msbuild 部分:

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

    C#部分:

    // <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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-10
      • 1970-01-01
      相关资源
      最近更新 更多