如何限制并发进程数?

时间:2008-12-22 03:44:39

标签: c#

我的情况如下:

  1. 我的应用程序只能启动固定次数(少于50次)。
  2. 由于业务需求,不允许单独的管理其他流程的中央流程。 (即,如果一个只涉及申请流程的好解决方案仍然可以接受)
  3. 我使用C#开发应用程序,因此首选托管解决方案。
  4. 我必须处理“意外”的情况,例如可以使用TaskManager终止进程。
  5. 我正在考虑使用系统范围的互斥锁的解决方案。然而,它在“出乎意料”的情况下并没有像它留下“废弃的”互斥体那样很好地存活下来。如果这是一个好方法,我可以问一下“忽略”被遗弃的互斥量是什么?

6 个答案:

答案 0 :(得分:2)

一种方法是查询进程列表并计算当前活动的实例数。另一种方法,更多的是,广播UDP并计算响应的数量。我已将此模式用于与作业处理器相关的分布式方案。

HTH

非洲科尔比

答案 1 :(得分:0)

您可以使用共享内存段并在每次打开应用程序时递增计数,并在应用程序关闭时递减。一个更简单的方法可能是使用您在问题中提到的进程间信号量。

答案 2 :(得分:0)

当进程通过“意外”事件(例如任务管理器进程终止)终止时,它应抛出一个ThreadAbortException。你应该尝试将你的互斥锁包装在某种try / finally中,以便在线程中止时释放它。

我不是百分之百确定这是真的,但应该有某种方式来应对这种情况。

答案 3 :(得分:0)

扩展进程列表方法,将WMI.NET C#一起使用可能如下所示:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Management;

namespace WmiProc
{
    class Program
    {
        static void Main(string[] args)
        {
            ManagementScope ms = new System.Management.ManagementScope(
                @"\\myserver\root\cimv2");

            var oq = new System.Management.ObjectQuery(
                "SELECT * FROM Win32_Process where Name='myprocname'");
            ManagementObjectSearcher query1 = new ManagementObjectSearcher(ms, oq);
            ManagementObjectCollection procsCollection = query1.Get();
            Console.WriteLine("process count:{0}", procsCollection.Count);
        }
    }
}

编辑:开始时间会有一些分离,这样就不太可能同时运行太多进程。您必须测试环境中的特定行为。

也许您可以定期检查单独(长时间运行)流程中的流程计数,并根据某些标准(例如最新流程)终止多余流程。

答案 4 :(得分:0)

好吧,你可以使用已命名的Mutex实例。

对互斥锁使用个人命名方案,请求此名称并检查已创建此名称的互斥锁的结果。

如果您使用带增量元素的命名方案,您可以尝试使用增量元素升序的所有互斥锁名称,并计算这样的数量,创建了多少个互斥锁。

使用已发布的互斥锁处理需要一些改进,但这似乎微不足道。

class Program
{
    private static Mutex mutex = null;

    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);

        int count = Program.CheckInstanceCount();
        Console.WriteLine("This is instance {0} running.", count);
        Console.Read();
    }

    static void CurrentDomain_ProcessExit(object sender, EventArgs e)
    {
        Program.mutex.ReleaseMutex();
        Program.mutex.Close();
    }

    private static int CheckInstanceCount()
    {
        int result = 0;
        bool created = false;

        for (int i = 0; i < 50; i++)
        {
            /* try to create a mutex with this name, 
             * if it does exist, another instance 
             * of this program is running
             */
            mutex = new Mutex(true, string.Concat(AppDomain.CurrentDomain.FriendlyName, i.ToString()), out created);
            if (created)
            {
                // this instance is instance #i currently running
                result = i;
                break;
            }
        }
        return result;
    }
}

答案 5 :(得分:0)

我无法为上述答案添加评论,但通过阅读上述答案和评论,您似乎应该能够将互斥锁与流程实例检查结合起来。

// You can use any System wide mutual exclusion mechanism here
bool waitAndLockMutex();
void unlockMutex();

// returns the number of processes who use the specified command
int getProcessCount();

void main() {
    try {
        waitAndLockMutex();
        if (getProcessCount() > MAX_ALLOWED)
            return;

        doUsualWork();

    } finally {
        unlockMutex();
    }
}

请注意,上面的代码仅用于说明目的,并且可以使用.NET轻松编写声明函数调用的主体

编辑:

如果您不想计算感兴趣的过程,可以使用全局互斥。不确定.NET是否公开了。但要点是你可以获得所有的互斥体直到MAX,并且在这个过程中如果你得到一个尚未创建或被抛弃的Mutex,那么你继续让流程启动,否则退出说超过最大数量

void main() {
    for (int i = 0; i < MAX; ++i) {
        int status = TryToAcquireMutex("mutex" + i);
        continue if (status == locked);
        if (status == success || status == WAIT_ABANDONED) {
            doUsusalWork();
        }
    }
}