Как обрабатывать события закрытия приложения с помощью C # - PullRequest
1 голос
/ 22 февраля 2012

У меня есть служба Windows, которая следит за папкой для новых создаваемых файлов. Когда файл добавляется в папку, служба отправляет файл для обработки во 2-е приложение.Второе приложение на самом деле является консольным приложением, но оно установлено как «Приложение Windows», чтобы избежать создания окна консоли.Служба и второе приложение работают на сервере.Чтобы реализовать только один файл для обработки каждый раз, во 2-м приложении был реализован семафор, например:

public class Program
{
    static Semaphore semaphore;
    [STAThread]
    static void Main(string[] args)
    {
        StartupConfigurator startConfig = new StartupConfigurator();
        semaphore = new Semaphore(1, 1, "2ndApp");
        semaphore.WaitOne();
        startConfig.StartProcessCommandLine(args);
        semaphore.Release(1);
        Environment.Exit(1);
    }
}

Это прекрасно работает, пока приложение корректно завершает работу и семафор освобождается.Во 2-м приложении есть строка кода, которая во время выполнения просто зависает (в основном она пытается войти на сервер, но не удается, причины для 2-го приложения не известны), она просто висит там.Из-за способа написания сервиса он будет запускать новый экземпляр 2-го приложения каждый раз, когда создается новый файл.Это может быть добавление нового файла или добавление нескольких файлов одновременно в отслеживаемую папку.Например, если в просматриваемую папку добавлено 4 файла, служба запустит 4 экземпляра 2-го приложения.Второе приложение завершает файл, семафор освобождается и обрабатывается следующий файл.Это работает нормально, если так, то есть выходит изящно.В случае зависания единственный способ возобновить обработку - это закрыть все экземпляры из диспетчера задач, и не поможет только завершение проблемного экземпляра, все они должны быть завершены.

обсуждение подобной темы здесь , но я не могу знать, как его использовать.Есть ли способ для второго приложения узнать, что оно было принудительно завершено и семафор может быть освобожден.

С уважением.

Ответы [ 2 ]

0 голосов
/ 22 февраля 2012

Если второе приложение запускается только службой, я бы поместил код, синхронизирующий обработку, в службу.

Служба будет знать, запущено ли приложение обработки, и когда оно будет завершено, оно запустит другое. Само приложение может иметь простую проверку, если другое приложение уже запущено (через семафор или мьютекс), и завершить работу, если оно есть.

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

0 голосов
/ 22 февраля 2012

Есть ли способ для 2-го приложения узнать, что оно было принудительно завершено и семафор может быть освобожден.

Нет, когда процесс завершается, нетвозможность очистить, выполнить, наконец, блоки и т. д. См. this .Лучше всего запустить операцию зависания в отдельном потоке и вызвать соединение в потоке, чтобы дождаться завершения операции.Пример:

bool completed = false;
try
{
   Thread thread = new Thread(() => startConfig.StartProcessCommmandLine(args));
   thread.IsBackground = true;
   thread.Start();
   bool completed = thread.Join(60000); // 60s timeout
}
finally
{
   semaphore.Release(1);
}
Environment.Exit(completed ? 0 : 1);

Обычно код выхода 0 считается нормальным.Try / catch важен, потому что если ваш поток генерирует необработанное исключение, мы хотим убедиться, что семафор освобожден до того, как процесс будет остановлен.

...