【问题标题】:Closing a Process that was started via a thread关闭通过线程启动的进程
【发布时间】:2012-04-20 12:53:36
【问题描述】:

我目前正在处理一个 c# 项目,并且正在使用 System.Diagnostic.Process 类。

当我的程序启动时,它会创建一个新线程,并在每个线程中启动一个不同的进程。

有时我需要检查程序中的设置,以查看每个进程是否应该继续运行或是否应该停止,但我不知道如何引用由某个线程启动的进程。每个线程我在进程启动时都给了一个名字,但我的理解是 c# 创建线程,启动进程然后关闭线程,即使进程仍在运行并且仍在接收输出。

有没有办法可以找出哪个进程由哪个线程启动并取消该进程的运行。

但我看不出如何使用此方法和字典来停止基于此线程名称的进程。

更新 正如下面的请求是我正在使用的在线程中创建每个进程的代码。我在字典中使用线程,以便可以从 outputreceived 事件中引用它,但如果我需要关闭进程,我不确定该怎么做。

Thread worker = new Thread(new ThreadStart(() => startProducts(product.Value[0].startScript, product.Value[0].productName)));
                worker.IsBackground = false;
                worker.Name = product.Value[0].productName;
                worker.Start();
                logging.logger(string.Format("Starting product '{0}'", product.Value[0].productName));

线程调用的方法如下,这是每个进程启动的地方。每个进程都保证有一个不同的命名线程,永远不会有两个同名的线程。

private void startProducts(string startScript, string product)
        {
            Process startProductProcess = new Process();
            startProductProcess.StartInfo.FileName = startScript;
            if ( configManagement.productConfig[product][0].requireArguments == true )
            {
                startProductProcess.StartInfo.Arguments = configManagement.productConfig[product][0].arguments;
            }
            startProductProcess.StartInfo.UseShellExecute = false;
            startProductProcess.StartInfo.RedirectStandardOutput = true;
            StringBuilder processOutput = new StringBuilder("");
            startProductProcess.OutputDataReceived += new DataReceivedEventHandler(startProductProcess_OutputDataReceived);
            startProductProcess.Exited += new EventHandler(startProductProcess_Exited);
            processTag.Add(startProductProcess, product);
            startProductProcess.Start();
            //Process localByName = Process.GetProcessById(startProductProcess.Id);
            startProductProcess.BeginOutputReadLine();
            logging.logger(string.Format("Started {0} with: {1} {2}", product, 
                startProductProcess.StartInfo.FileName, startProductProcess.StartInfo.Arguments));
        }

【问题讨论】:

  • 听起来您应该使用字典,并使用 StatusEnum 之类的内容将每个进程保存到字典中。
  • 我想我是为了触发输出事件,我会添加一些代码,这样可能会有所帮助

标签: c# multithreading system.diagnostics


【解决方案1】:

为什么要使用线程名称?如果您要将此活动集中起来,您将不知道哪个线程将运行任何特定进程。

如果您正在管理进程,请定义一个“managedProcess”类,该类可以包含进程名称、进程 EXE 路径、进程句柄、在句柄上等待进程完成的线程、任何状态枚举、任何互斥锁以保持字段线程安全,启动和停止它的方法 - 与进程有关的任何事情。将此 managedProcess 类的实例推送到您的容器中。

恕我直言,除了调试之外,忘记线程名称。

终止 - 在您的 stop() 方法中,您可以尝试发布 WM_CLOSE,(您可以直接执行此操作,还是 P/Invoke?),等待几秒钟以查看线程等待是否发出进程信号已关闭,如果没有,请调用 TerminateProcess(),(或任何用于 TerminateProcess 的托管事物)。

【讨论】:

    【解决方案2】:

    除非您有通过使用单独的线程创建每个进程来解决的特定需求,否则不要使用线程。如果您正在寻找的只是在代码中识别给定进程的唯一方法,则可以使用 给线程的名称作为字典中的标识符。

    Dictionary<string, Process> processesByName = new Dictionary<string, Process>();
    Process firstProcess = ... //Start your process
    Process secondProcess = ... //Start your process
    processesByName.Add("FirstProcessName", firstProcess);
    processesByName.Add("SecondProcessName", secondProcess);
    

    之后,您可以按您指定的名称拉取给定进程,并随心所欲地与之交互。

    Process process = processesByName["FirstProcessName"];
    if (!process.HasExited)
    {
        process.CloseMainWindow();
        process.Close();
    }
    

    【讨论】:

    • 感谢您的帮助,但这不起作用,因为在 for each 循环中启动了一个新进程,因此我无法命名每个进程,因此我不知道要关闭哪些进程它
    • @Boardy 让我们备份。您正在 foreach 循环中创建进程。每个线程是否都有一个启动 N 个进程的循环,或者该循环是否产生 N 个线程,每个线程启动一个进程?每个进程理论上是否具有相同的名称,或者线程名称对于给定进程是否唯一?
    • @Boardy 如果你能发布代码来展示你是如何创建线程和进程的,那就太好了。
    • 我已在线程启动进程的位置添加了您请求的 cod。为了回答您之前的问题,保证每个线程都有一个单独的名称。我不会知道进程的名称,这就是我使用线程名称的原因。感谢您的帮助
    • 因此您有一个唯一的进程名称,并且您已经将其与字典中的进程相关联。您需要如何确定需要关闭哪个进程以及名称为何如此重要?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多