Как решить эту конкретную проблему с потоками - PullRequest
2 голосов
/ 09 июня 2009

Используя код из следующей статьи, я реализовал собственный ThreadPool: http://www.developer.com/net/article.php/3783756

Вот чего я хочу добиться: При запуске через таймер служба должна запрашивать базу данных каждые 5 секунд для выполнения новых заданий. Задание - это в основном только информация о программе командной строки, которую нужно запускать с аргументами.

Одновременно может выполняться до 50 или более из этих программ. Программа может быть запущена за пару секунд, минут, а также часов. Служба должна постоянно контролировать эти программы, то есть, например, она должна иметь возможность убивать программу по запросу.

Используя реализацию ThreadPool, описанную выше, я начал ставить в очередь программы, которые должны быть выполнены, и мог видеть, когда служба действительно их выполняла. Пока проблем нет. Однако механизм здесь работает так:

ThreadPool создает рабочий поток и запускает его. Всякий раз, когда программа ставится в очередь, рабочая нить замечает это и вызывает делегат, который по существу создает экземпляр объекта System.Diagnostics.Process и запускает внешнюю программу. Затем поток завершает свою работу и сможет запускать дальнейшие программы. Однако ... когда нет программы для запуска, таймер простоя заставляет потокового менеджера уничтожить поток и тем самым прервать запущенный процесс.

Это не то, что мне нужно. У кого-нибудь есть идея, как лучше описать сценарий, который я описал?

Ответы [ 3 ]

3 голосов
/ 09 июня 2009

1) Почему смерть потока в этом процессе приводит к смерти другого, запущенного процесса? Если вы ответите на этот вопрос, вы решите свою проблему.

2) Это похоже на довольно паршивую и довольно наивную статью ThreadPool. Ознакомьтесь с серией Джо Даффи в пользовательском пуле потоков ( часть 1 , часть 2 и часть 3 ). Такой код на удивление сложен и сам по себе является серьезным бременем для обслуживания.

3) (Реальный ответ) Почему вы вообще используете поток потоков для этого? Ваш пул потоков когда-либо использует только один поток за раз, почему бы просто не использовать таймер и запустить основной поток? Делает ли ваше приложение другие вещи, кроме как в пользовательском интерфейсе, который вам нужен, чтобы реагировать?

Избавьтесь от пула потоков, в этом нет необходимости, это усложняет вашу жизнь, а пулы потоков вообще не предназначены для размещения долгосрочных задач. Вот для чего нужны отдельные темы. Если вам нужно запустить таймер в отдельном потоке, просто создайте поток для его обработки и используйте этот идентичный поток для запуска всех ваших процессов. Затем вы можете отслеживать свое состояние процесса в одном, центральном, разумном месте. :)

1 голос
/ 09 июня 2009

Вы уверены, что пул потоков является оптимальным способом справиться с этим? Создание нового потока для каждого процесса, который будет в основном бездействующим, но должен присутствовать, пока процесс не завершится, мне кажется пустой тратой потока.

Я бы реализовал все это с помощью одного потока и словаря процессов. Поток будет периодически запрашивать базу данных и все процессы, чтобы узнать, какие действия необходимо выполнить.

0 голосов
/ 09 июня 2009

AFAIK, процессы, порожденные Process.Start, будут продолжать выполняться, даже если завершается поток, вызывающий Process.Start. Следующий код иллюстрирует это. После выхода из основной программы LongRunningApp.exe продолжит работу:

static void Main(string[] args)
{
    Process p = new Process();
    ProcessStartInfo psi = new ProcessStartInfo(@"C:\LongRunningApp.exe");
    psi.CreateNoWindow = true;
    psi.UseShellExecute = false;
    p.StartInfo = psi;
    p.Start();
    Console.ReadLine();
}
...