终止从嵌套线程启动的多个进程.C#.
本文关键字:进程 启动 嵌套 线程 终止 | 更新日期: 2023-09-27 18:31:45
我是编程新手。我有一个启动线程的表单应用程序。形成那里启动了 4 个新线程。其中每个线程都执行一系列命令行过程,如下所示:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WorkingDirectory ="C:''BLA''bin_windows";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.CreateNoWindow = true;
startInfo.FileName = "SomeProcess"
Process p = Process.Start(startInfo);
p.WaitForExit();
当表单应用程序关闭时,它会中止第一个线程(而不是 4 个单独的线程)。现在我的问题是如何在关闭表单时强制进程"p"退出?我尝试了以下方法:
foreach (Process p in System.Diagnostics.Process.GetProcessesByName("SomeProcess"))
{
try
{
p.Kill();
p.WaitForExit(); // possibly with a timeout
}
catch
{ continue; }
}
然而,这种方法对我来说似乎有点残酷,并不总是奏效......有没有办法让我只识别我自己启动的进程,然后终止它们?任何建议都非常感谢。谢谢
你对你运行的进程几乎没有控制权。杀死他们是一种方式。如果进程是一个窗口应用程序(即有一个窗口),您可以尝试向它发送一条WM_CLOSE
消息,这相当于单击窗口上的关闭按钮。同样,应用程序必须有一个窗口,可见或隐藏,因此它不适用于每个应用程序。大多数应用程序都有窗口,即使不可见。
const uint WM_CLOSE = 0x10;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, uint uMsg, int wParam, int lParam);
Process p = Process.GetProcessesByName("notepad").FirstOrDefault();
if(p != null)
{
IntPtr hWnd = p.MainWindowHandle;
SendMessage(hWnd, WM_CLOSE, 0, 0);
}
要仅杀死/关闭您生成的进程,只需保留其Process
对象,或者如果您想使用我给您的方法,至少保留p.MainWindowHandle
。为此,在您的类中具有类型 ConcurrentBag<Process>
(或 ConcurrentBag<IntPtr>
)的公共属性。它已经是线程安全的。
编辑
正如有人指出的那样,您可以这样做来关闭进程的主窗口:
p.CloseMainWindow()
如果你的程序不应该一次运行两次,你可以在单例上使用某种进程管理器:
internal sealed class ProcessManager
{
private readonly IList<Process> processes;
#region Singleton
private static readonly object locker = new object();
private static volatile ProcessManager instance;
private ProcessManager()
{
processes = new List<Process>();
}
public static ProcessManager Instance
{
get
{
if (instance == null)
{
lock (locker)
{
if (instance == null)
{
instance = new ProcessManager();
}
}
}
return instance;
}
}
#endregion
public void AddProcess(Process process)
{
lock(processes)
{
processes.Add(process);
}
}
public void TerminateAll()
{
lock(processes)
{
foreach (Process p in processes)
{
try
{
p.Kill();
p.WaitForExit(); // possibly with a timeout
}
catch
{
continue;
}
}
}
}
}
用法:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WorkingDirectory ="C:''BLA''bin_windows";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.CreateNoWindow = true;
startInfo.FileName = "SomeProcess"
Process p = Process.Start(startInfo);
ProcessManager.Instance.AddProcess(p);
p.WaitForExit();
如果你不希望在你的程序中使用静态的东西(例如,你可以有一些实例),你可以使用这个类,但没有单例,并把它的单个实例提供给每个线程。
如果要关闭进程,则无需 P/Invoke 并发送WM_CLOSE消息,只需在 Process 实例上调用 CloseMainWindow() 方法(这将为您发送WM_CLOSE)。然后,您可以使用 Close() 方法对其进行跟进,以释放它的本地视图。
跟踪您启动的流程也相当容易。
public static ConcurrentBag<Process> processes = new ConcurrentBag<Process>();
在创建流程时存储流程。
Process process = ... //Create your process
processes.Add(process);
然后循环访问并关闭它们。
foreach (var process in processes)
{
if (!process.HasExited)
{
process.CloseMainWindow();
process.Close();
}
}