如何使用C#处理应用程序关闭事件

时间:2012-02-22 07:00:05

标签: c# semaphore

我有一个监视文件夹的Windows服务,用于创建新文件。当文件被添加到文件夹时,服务会将文件发送到第二个应用程序。 第二个应用程序实际上是一个控制台应用程序,但设置为“Windows应用程序”以避免创建控制台窗口。该服务和第二个应用程序都在服务器上运行。 要实现每次只处理一个文件,第二个应用程序中已实现了一个信号量,如下所示:

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

只要应用程序正常退出并且信号量被释放,这就可以正常工作。 在第二个应用程序中,有一行代码在执行时只是挂起(它基本上是尝试登录到服务器,但是失败,原因超出了第二个应用程序的范围),它只是挂起。 由于服务的编写方式,每次创建新文件时,它都会启动第二个应用程序的新实例。它可以添加新文件或一次添加多个文件到监视文件夹。例如,如果4个文件被删除到监视文件夹,该服务将启动第2个应用程序的4个实例。第二个应用程序完成一个文件,释放信号量并处理下一个文件。如果它以这种方式工作,即可正常退出,即可正常工作。在它挂起的情况下,恢复处理的唯一方法是从任务管理器关闭所有实例,结束只是陷入困境的实例也无济于事,所有实例都必须结束。

对类似主题here进行了讨论,但我无法知道如何使用它。 有没有办法让第二个应用程序知道它已被强制结束并且信号量可以被释放。

问候。

2 个答案:

答案 0 :(得分:0)

  

有没有办法让第二个应用程序知道它已被强制结束并且信号量可以被释放。

不,当进程被终止时,没有机会清理,执行finally块等等。请参阅this。最好的办法是在单独的线程上启动挂起操作,并在线程上调用join以等待操作完成。样本:

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很重要,因为如果你的线程抛出一个未处理的异常,我们希望确保在进程被关闭之前释放信号量。

答案 1 :(得分:0)

如果第二个应用程序仅由服务启动,我会将同步处理的代码放在服务中。

服务将知道处理应用程序是否已启动,何时完成,它将启动另一个应用程序。如果另一个应用程序已经在运行(通过信号量或互斥锁),应用程序本身可以只进行简单检查,如果是,则退出。

这样服务可以杀死无响应的应用,指定运行超时,基本上管理处理。