2009-06-09 3 views
2

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

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

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

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

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

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

ответ

3

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

2) Это похоже на довольно паршивую и довольно наивную статью ThreadPool. Проверьте Joe Duffy's серии на пользовательском пуле потоков (part 1, part 2 и part 3). Код, такой как это удивительно сложный, и существенное бремя обслуживания самостоятельно.

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

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

+0

Hm. Фактически это был запрос клиента работать с потоками (что он и сделал, а теперь хочет, чтобы мы это сделали в .NET). Теперь, когда я сделал некоторый опыт в этой «паршивой» реализации threadpool, я заметил, что это не имеет никакого смысла. Поскольку запуск внешней программы уже порождает новые потоки, которые работают параллельно. Кажется, что сборка, управляющая процессами, кажется более правильной ... – Mephisztoe

1

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

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

+0

Вы правы, это может иметь смысл работать с коллекцией. – Mephisztoe

0

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(); 
}