我本来想说你可以使用一个命名的 Mutex,但是考虑到 ASP.Net 的多线程野兽,你不能保证拥有的线程就是释放它的同一个线程。这可能会导致问题。所以...
最简单的方法可能是使用文件系统。
让控制台应用实例化一个FileSystemWatcher 来监视一个目录,两个进程都可以访问该目录以进行更改,并为Created event 连接一个事件处理程序,如下所示:
internal static bool ShutDownRequested { get ; set ; }
private static void OnCreated( object sender , FileSystemEventArgs fileSystemEventArgs )
{
FileSystemWatcher watcher = (FileSystemWatcher) sender ;
ShutDownRequested = true ;
File.Delete( fileSystemEventArgs.FullPath ) ;
watcher.Created -= OnCreated ;
}
static void Main()
{
using ( FileSystemWatcher watcher = new FileSystemWatcher( @"\some\common\directory" , "foobar.shutdown.requested" ) )
{
watcher.Created += OnCreated;
while ( !ShutDownRequested )
{
DoSomethingUseful() ;
}
}
return ;
}
当您想要关闭控制台应用程序时,只需创建控制台应用程序所期望的文件。控制台应用程序的事件处理程序在工作线程上捕获事件,然后可以设置全局关闭标志,以便主线程可以在第一个合适的时间正常关闭,或者事件处理程序可以简单地调用Environment.Exit(int) 并强制它关闭。不要忘记在完成工作后删除哨兵文件来收拾东西(这是唯一礼貌的做法)。
这就是我会做的,但是,我不喜欢过度思考的事情。
在过度思考时,您可以以类似的方式使用命名事件。在您的 ASP.Net 服务中,创建了一个最初未发出信号的命名事件:
// start console app
EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.ManualReset,"foobar.shutdown.signal");
SpawnConsoleApp() ;
然后,何时关闭控制台应用程序:
// shutdown time
wh.Set() ;
(别忘了把等待把手放在安全的地方)
在您的控制台应用程序中,您需要定期检查信号:
static void Main()
{
EventWaitHandle wh = EventWaitHandle.OpenExisting( "foobar.shutdown.signal" ) ;
while( !wh.WaitOne(0) )
{
DoSomethingUseful() ;
}
wh.Set() ; // acknowledge the signal
return ;
}