Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
由C#启动的应用程序在主线程关闭之前一直作为运行进程_C#_Com_Process - Fatal编程技术网

由C#启动的应用程序在主线程关闭之前一直作为运行进程

由C#启动的应用程序在主线程关闭之前一直作为运行进程,c#,com,process,C#,Com,Process,我的目标是使用C#控制第三方应用程序。第三方应用程序可以由COM引用控制 我已经在我的简单控制台应用程序中添加了引用,我可以看到类和方法没有问题 以下行触发第三方应用程序启动。确实如此。您可以在Taskmanager/processs(mfl32.exe)中愉快地看到它: 当我的控制台应用程序退出时,mfl32.exe仍在进程列表中-这是意料之中的,因为我没有调用关闭它。然后我添加了这一行: mfl.Quit(); 现在,当我的控制台应用程序运行时,它会触发要启动的mfl32.exe,当我的控

我的目标是使用C#控制第三方应用程序。第三方应用程序可以由COM引用控制

我已经在我的简单控制台应用程序中添加了引用,我可以看到类和方法没有问题

以下行触发第三方应用程序启动。确实如此。您可以在Taskmanager/processs(mfl32.exe)中愉快地看到它:

当我的控制台应用程序退出时,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();
    }
}
名称空间lt
{
类螺纹试验
{
公共无效激光测试()
{
WriteLine(“工作线程已启动…”);
MFL32.Application mfl=新的MFL32.Application();
int i=0;
而(i<50000)
{
i++;
}
mfl.Quit();
WriteLine(“工作线程现在已完成!”);
}
void laser\u AppQuit()//已触发退出事件处理程序
{
WriteLine(“QUIT方法已被捕获。它应该会终止lfm32.exe进程”);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
threadtest workerObject=新的threadtest();
线程workerThread=新线程(workerObject.LaserTest);
workerThread.Start();
Console.WriteLine(“到达主线程的末尾”);
Console.ReadKey();
}
}
}


你知道为什么触发的exe只在主控制台应用程序终止时终止,而不是在到达单独线程的末尾时终止吗?

我假设COM dll中没有正确释放某些内容。我会尝试在单独的应用程序域中运行LaserTest。一旦程序集加载到.NET中,它将保持加载状态,除非应用程序域被销毁。或者,您可以创建单独的“launcher”程序集,在线程中运行launcher程序集,并在完成COM操作后强制退出launcher程序集。对于在单独的应用程序域中运行:

  var domain = AppDomain.CreateDomain("LaserDomain");
  domain.DoCallBack(() => {
      // dummy wait - run laser test here
      Thread.Sleep(5000);
      AppDomain.Unload(AppDomain.CurrentDomain);
  });

我假设COM dll中没有正确发布某些内容。我会尝试在单独的应用程序域中运行LaserTest。一旦程序集加载到.NET中,它将保持加载状态,除非应用程序域被销毁。或者,您可以创建单独的“launcher”程序集,在线程中运行launcher程序集,并在完成COM操作后强制退出launcher程序集。对于在单独的应用程序域中运行:

  var domain = AppDomain.CreateDomain("LaserDomain");
  domain.DoCallBack(() => {
      // dummy wait - run laser test here
      Thread.Sleep(5000);
      AppDomain.Unload(AppDomain.CurrentDomain);
  });

即使调用了
mfl.Quit()
,当有未完成的COM引用时,第三方程序也可能保持活动状态。这有点奇怪,因为“Quit()”方法的正常语义是强制进程退出(有序)并使任何COM引用无效

根据设计,.Net在保存引用的变量(好的,保存对应用程序的COM引用的对象的引用的变量)超出范围时,不会对COM对象调用Release(),因为.Net是垃圾收集的

Release()

我本以为RCW对象可以
Dispose()
处理,但事实并非如此。也许有技术原因,也许dispose模式是在.NET1.0的开发过程中才引入的,直到太晚才改变RCW的行为

在任何情况下,要强制RCW在其COM引用上调用
Release()
,请调用:

  Marshal.ReleaseComObject(mfl);

在调用
Quit()
方法后尝试此操作,看看它是否会改变第三方程序的行为。

即使在调用
mfl.Quit()
后,第三方程序仍可能在有未完成的COM引用时保持活动状态。这有点奇怪,因为“Quit()”方法的正常语义是强制进程退出(有序)并使任何COM引用无效

根据设计,.Net在保存引用的变量(好的,保存对应用程序的COM引用的对象的引用的变量)超出范围时,不会对COM对象调用Release(),因为.Net是垃圾收集的

Release()

我本以为RCW对象可以
Dispose()
处理,但事实并非如此。也许有技术原因,也许dispose模式是在.NET1.0的开发过程中才引入的,直到太晚才改变RCW的行为

在任何情况下,要强制RCW在其COM引用上调用
Release()
,请调用:

  Marshal.ReleaseComObject(mfl);

在调用
Quit()
方法后尝试此操作,看看它是否会改变第三方程序的行为。

此操作非常有效。比捕获退出事件然后尝试手动终止进程要友好得多!非常感谢。这个很好用。比捕获退出事件然后尝试手动终止进程要友好得多!非常感谢你。