【问题标题】:Limit the maximum process-instances by counting the amount of Mutexes?通过计算互斥量来限制最大进程实例?
【发布时间】:2014-08-18 06:49:03
【问题描述】:

我已经编写了下一个通过MUTEX 防止多实例化的代码,但我想通过允许设置允许的最大实例数来扩展它的功能,所以我应该可以决定是否只允许单个实例或只有 3 个实例的多实例(例如)。

我试图弄清楚如何计算进程的互斥量,但我没有找到任何相关信息。

另一方面,我在 StackOverflow 中找到了很多帖子,解释如何通过文件名计算进程数量,我对这些都不感兴趣,因为我选择了 MUTEX 检测对我来说更安全。

有人能帮我这个心血来潮吗?

这就是我所做的一切:

Namespace My

    Partial Friend Class MyApplication

#Region " Properties "

        ''' <summary>
        ''' Gets the current process mutex identifier.
        ''' </summary>
        ''' <value>The current process mutex identifier.</value>
        ''' <exception cref="System.FormatException">The specified value is not a valid GUID format.</exception>
        Private ReadOnly Property MutexID As String
            Get
                ' Define a Golabl Unique Identifier to name the Mutex.
                Dim Id As String = "b045ce40-2863-4ce7-a7df-8afca8214454"

                If Guid.TryParse(input:=Id, result:=New Guid) Then
                    Return Id
                Else
                    Throw New FormatException("The specified value is not in a valid GUID format.")
                End If

            End Get
        End Property

        ''' <summary>
        ''' Gets the maximum instances allowed for this process.
        ''' </summary>
        ''' <value>The maximum instances allowed for this process.</value>
        Private ReadOnly Property MaxInstances As Integer
            Get
                Return 2
            End Get
        End Property

#End Region

#Region " Private Methods "

        ''' <summary>
        ''' Determines whether this is the unique instance that is running for this process.
        ''' </summary>
        ''' <returns><c>true</c> if this is the unique instance; otherwise, <c>false</c>.</returns>
        Private Function IsUniqueInstance() As Boolean

            Dim mtx As Threading.Mutex = Nothing

            Try
                mtx = Threading.Mutex.OpenExisting(name:=Me.MutexID)
                mtx.Close()
                mtx = Nothing
            Catch
                mtx = New Threading.Mutex(initiallyOwned:=True, name:=Me.MutexID)
            End Try

            Return mtx IsNot Nothing

        End Function

#End Region

#Region " Event-Handlers "

        ''' <summary>
        ''' This occurs when the application starts, before the startup Form is created.
        ''' </summary>
        ''' <param name="sender">The source of the event.</param>
        ''' <param name="e">The <see cref="ApplicationServices.StartupEventArgs"/> instance containing the event data.</param>
        Private Sub MyApplication_Startup(ByVal sender As Object, ByVal e As ApplicationServices.StartupEventArgs) _
        Handles Me.Startup

            ' If there is more than one instance running of this process with the same mutex then...
            If Not Me.IsUniqueInstance Then ' Prevent multi-instancing.

                MessageBox.Show("This is a limited demo, to run multiple instances please purchase the program.",
                               Application.Info.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error)

                ' Cancel the application execution.
                e.Cancel = True

            End If

        End Sub

#End Region

    End Class ' MyApplication

End Namespace

更新

这是我正在尝试的代码,我在应用程序事件、表单构造函数、加载和显示事件中都尝试过,但未检测到多实例。

    Private Sub test() Handles Me.Startup

        Using semaphore As New Semaphore(3I, 3I, "something")

            If Not semaphore.WaitOne(100I) Then
                MsgBox("Already max instances running")
                End
            Else
                MsgBox("test")
            End If

        End Using

    End Sub

【问题讨论】:

  • 您需要Semaphore 而不是Mutex
  • Already max instances running 消息框你看到了什么?
  • 不,我总是收到“测试”消息
  • 我理解这个问题。您应该删除该 using 语句。您需要将 semaphore 变量作为实例变量而不是局部变量。当您的应用程序结束时Dispose 它。我使用了using 语句,因为它是Main 方法。那么这应该可以工作。
  • 不,它与Semaphore 没有任何关系,除非您的线程使用此信号量实例并调用semaphore.WaitOne。您的信号量实例应该不受任何其他线程的影响。另请注意,您不应多次调用test 方法。多次调用此方法会让人觉得有多个进程正在运行,即使它们没有运行。

标签: .net vb.net winforms mutex single-instance


【解决方案1】:

Mutex 用于互斥。它最多只允许一个线程继续进行。如果您需要允许线程数(在这种情况下为进程)继续进行,您需要 Semaphore 而不是互斥锁。

C# 示例:

private static void Main()
{
    using (Semaphore semaphore = new Semaphore(3, 3, Assembly.GetExecutingAssembly().GetName().FullName))
    {
        if (!semaphore.WaitOne(100))
        {
            MessageBox.Show("Already max instances running");
            return;
        }

        //Start your application here
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

VB.Net 示例:

Private Shared Sub Main()
    Using semaphore As New Semaphore(3, 3, Assembly.GetExecutingAssembly().GetName().FullName)
        If Not semaphore.WaitOne(100) Then
            MessageBox.Show("Already max instances running")
            Return
        End If

       'Start your application here
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        Application.Run(New Form1())
    End Using
End Sub

P.S: 使用http://converter.telerik.com/ 将代码从 C# 转换为 VB

【讨论】:

  • 谢谢,但您提供的代码仅在 CLI 应用程序中有效,相同的代码在 GUI 应用程序中不起作用,它没有检测到多实例,而且您正在使用程序集名称但我不确定这是否意味着检测是通过应用程序的名称进行的(可以由用户重命名,我已经指定我更愿意避免使用这些技术)或者只是一个安全 ID,例如一个 MUTEX,另一个问题是这是否会与我的应用程序的线程发生冲突,因为我的意图是限制进程实例而不是多线程应用程序上的线程,感谢您的回答
  • @ElektroStudios 这是一个通用答案,应该适用于所有应用程序。我尝试使用 GUI 应用程序(Winforms)并且它可以工作。应用程序名称不能由用户更改(您可能会考虑重命名进程文件,但程序集名称不能重命名)。我正在检查程序集名称,所以这不是问题。如果您愿意,可以将此代码更改为使用GUID。而且没有什么可以限制进程的数量,你所拥有的只是限制线程的数量,使用我们正在终止进程。
  • 我 100% 确定,这就是您所需要的。如果您在实现这一点时遇到问题,您可能需要发布您尝试过的代码。我会调查的。
  • @Sriram Sakthivel 在一个 VB.NET 空项目中,我刚刚将您提供的 using 块复制到表单构造函数中,我也尝试将其放入“加载”和“显示“ebent-handler,但一切正常,您能否上传该 gui 应用程序的源代码以了解您是如何实现信号量的?谢谢您的帮助。
  • 你不应该在构造函数中使用它。您应该在Main 方法中使用它。如果你在构造函数中使用而不是Return,你应该使用Environment.Exit(0)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-26
  • 1970-01-01
  • 2016-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多