c#启动的应用程序在主线程关闭之前一直作为运行进程运行
本文关键字:运行 一直 进程 启动 应用程序 线程 | 更新日期: 2023-09-27 18:16:19
我的目标是使用c#控制第三方应用程序。第三方应用程序可以通过COM引用来控制。
我已经在我的简单控制台应用程序中添加了引用,我可以看到类和方法没有问题。
下面一行触发第三方应用程序启动。确实如此。你可以看到它愉快地坐在Taskmanager/Processes (mfl32.exe)中:
MFL32.Application mfl = new MFL32.Application();
当我的控制台应用程序退出时,mfl32.exe仍在进程列表中-这是意料之中的,因为我没有调用关闭它。然后我添加了这一行:
mfl.Quit();
现在当我的控制台应用程序运行时,它触发mfl32.exe启动,当我的控制台应用程序关闭时,它终止mfl32.exe进程。
出现的问题是,我的代码要求调用这个应用程序在一个单独的线程。mfl32.exe进程不会在线程结束时终止,只会在控制台应用程序关闭时自行删除。当前代码如下所示:namespace lt
{
class threadtest
{
public void LaserTest()
{
Console.WriteLine("Worker thread started...");
MFL32.Application mfl = new MFL32.Application();
int i = 0;
while (i < 50000)
{
i++;
}
mfl.Quit();
Console.WriteLine("Worker thread now finished!");
}
void laser_AppQuit() // Quit event handler triggered
{
Console.WriteLine("The QUIT method has been caught. It should kill the lfm32.exe process");
}
}
class Program
{
static void Main(string[] args)
{
threadtest workerObject = new threadtest();
Thread workerThread = new Thread(workerObject.LaserTest);
workerThread.Start();
Console.WriteLine("End of main thread reached");
Console.ReadKey();
}
}
}
任何想法,为什么触发的exe只终止时,主控制台应用程序终止,而不是当它达到一个单独的线程结束?
即使在调用mfl.Quit()
之后,当有突出的COM引用它时,第三方程序可能仍然存活。这有点奇怪,因为"Quit()"方法的正常语义是强制进程退出(有序)并使任何COM引用无效。
根据设计,当持有引用的变量(好吧,持有RCW或持有应用程序的COM引用的运行时可调用包装器对象的引用的变量)超出作用域时,. net不会在COM对象上调用Release(),因为。net是垃圾收集的。
Release()
将只在COM对象上被调用,当你的进程(技术上是AppDomain)结束时,或者当垃圾收集器决定收集你的RCW对象时,这在一个短暂的控制台应用程序上将是'never'。
我本来期望RCW对象能够Dispose()
,但它们不是。也许是技术上的原因,也许在。net 1.0的开发过程中没有引入dispose模式来改变RCW的行为已经太晚了。
在任何情况下,要强制RCW在其COM引用上调用Release()
,调用:
Marshal.ReleaseComObject(mfl);
在调用Quit()
方法之后尝试一下,看看它是否改变了第三方程序的行为。
我认为有些东西没有在COM dll中正确释放。我会尝试在单独的应用程序域中运行LaserTest。一旦程序集被加载到。net中,它将保持加载状态,除非应用程序域被销毁。或者,您可以创建单独的"启动器"程序集,在线程中运行启动器程序集,并在启动器程序集中强制退出,一旦完成了COM的工作。至于在单独的应用程序域中运行:
var domain = AppDomain.CreateDomain("LaserDomain");
domain.DoCallBack(() => {
// dummy wait - run laser test here
Thread.Sleep(5000);
AppDomain.Unload(AppDomain.CurrentDomain);
});